<?php
namespace ComptaFlowUK\Services;

defined('ABSPATH') || exit;

class CreditNoteService {

    private static function prefix(): string {
        global $wpdb;
        return $wpdb->prefix . 'cfuk_';
    }

    public static function create(array $data, array $lines): int {
        global $wpdb;
        $p = self::prefix();

        $data['uuid'] = wp_generate_uuid4();
        $data['invoice_type'] = 'CREDIT_NOTE';
        $data['status'] = 'DRAFT';
        $data['created_by'] = get_current_user_id();
        $data['created_at'] = current_time('mysql');

        if (empty($data['invoice_number'])) {
            $data['invoice_number'] = NumberingService::nextCreditNoteNumber();
        }

        $totals = self::calculateTotals($lines);
        $data['subtotal'] = $totals['subtotal'];
        $data['total_vat'] = $totals['total_vat'];
        $data['total'] = $totals['total'];

        $wpdb->insert($p . 'invoices', $data);
        $cn_id = $wpdb->insert_id;

        self::saveLines($cn_id, $lines);

        JournalEntryGenerator::generateCreditNoteEntries(self::getById($cn_id), self::getLines($cn_id));

        return $cn_id;
    }

    public static function update(int $id, array $data, array $lines): bool {
        global $wpdb;
        $p = self::prefix();

        $totals = self::calculateTotals($lines);
        $data['subtotal'] = $totals['subtotal'];
        $data['total_vat'] = $totals['total_vat'];
        $data['total'] = $totals['total'];
        $data['updated_at'] = current_time('mysql');

        $wpdb->update($p . 'invoices', $data, ['id' => $id]);
        $wpdb->delete($p . 'invoice_lines', ['invoice_id' => $id]);
        self::saveLines($id, $lines);

        return true;
    }

    public static function delete(int $id): bool {
        global $wpdb;
        $p = self::prefix();
        $wpdb->delete($p . 'invoice_lines', ['invoice_id' => $id]);
        return $wpdb->delete($p . 'invoices', ['id' => $id]) !== false;
    }

    public static function getById(int $id): ?array {
        return InvoiceService::getById($id);
    }

    public static function getLines(int $id): array {
        return InvoiceService::getLines($id);
    }

    public static function getAll(string $search = '', string $status = '', int $limit = 50, int $offset = 0): array {
        return InvoiceService::getAll('CREDIT_NOTE', $search, $status, $limit, $offset);
    }

    public static function count(string $search = '', string $status = ''): int {
        return InvoiceService::count('CREDIT_NOTE', $search, $status);
    }

    public static function createFromInvoice(int $invoice_id): int {
        $invoice = InvoiceService::getById($invoice_id);
        if (!$invoice) {
            return 0;
        }

        $lines = InvoiceService::getLines($invoice_id);
        $data = [
            'client_id' => $invoice['client_id'],
            'issue_date' => gmdate('Y-m-d'),
            'currency' => $invoice['currency'],
            'notes' => sprintf(
                /* translators: %s: invoice number */
                __('Credit note for invoice %s', 'comptaflow-uk-by-meetempo'),
                $invoice['invoice_number']
            ),
            'converted_from' => $invoice_id,
        ];

        return self::create($data, $lines);
    }

    private static function saveLines(int $cn_id, array $lines): void {
        global $wpdb;
        $p = self::prefix();

        foreach ($lines as $i => $line) {
            $line_total = round(floatval($line['quantity']) * floatval($line['unit_price']), 2);
            $vat_amount = round($line_total * floatval($line['vat_rate']) / 100, 2);

            $wpdb->insert($p . 'invoice_lines', [
                'invoice_id' => $cn_id,
                'line_order' => $i,
                'description' => sanitize_text_field($line['description']),
                'quantity' => floatval($line['quantity']),
                'unit_price' => floatval($line['unit_price']),
                'vat_rate' => floatval($line['vat_rate']),
                'vat_code' => sanitize_text_field($line['vat_code'] ?? 'GB-20'),
                'account_code' => sanitize_text_field($line['account_code'] ?? '4010'),
                'line_total' => $line_total,
                'vat_amount' => $vat_amount,
                'gross_total' => $line_total + $vat_amount,
            ]);
        }
    }

    private static function calculateTotals(array $lines): array {
        $subtotal = 0;
        $total_vat = 0;

        foreach ($lines as $line) {
            $line_total = round(floatval($line['quantity']) * floatval($line['unit_price']), 2);
            $vat_amount = round($line_total * floatval($line['vat_rate']) / 100, 2);
            $subtotal += $line_total;
            $total_vat += $vat_amount;
        }

        return [
            'subtotal' => $subtotal,
            'total_vat' => $total_vat,
            'total' => $subtotal + $total_vat,
        ];
    }
}
