<?php

require_once __DIR__ . '/../documents/CommercialDocumentPdfRenderer.php';

class CrmQuotePdfService
{
    private $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function render(int $quoteId): array
    {
        if ($quoteId <= 0) throw new InvalidArgumentException('Cotización inválida.');
        $quote = $this->loadQuote($quoteId);
        if (!$quote) throw new RuntimeException('Cotización no encontrada.');
        $items = $this->loadItems($quoteId);
        $company = $this->companySettings();
        $document = $this->documentData($quote, $items, $company);
        return array(
            'content' => (new CommercialDocumentPdfRenderer())->render($document),
            'filename' => $this->safeFilename((string)$quote['quote_number']) . '.pdf',
            'quote_number' => (string)$quote['quote_number'],
        );
    }

    private function loadQuote(int $quoteId)
    {
        $stmt = $this->pdo->prepare("SELECT q.*,o.title AS opportunity_title,o.owner_name,
            c.customer_name,c.legal_name,c.customer_tax_id,c.email,c.phone,c.address,c.district,c.city,c.region,c.country AS customer_country,c.payment_terms,c.facto_payment_term
            FROM crm_quotes q
            LEFT JOIN crm_opportunities o ON o.id=q.opportunity_id
            JOIN crm_customers c ON c.id=q.customer_id
            WHERE q.id=? LIMIT 1");
        $stmt->execute(array($quoteId));
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }

    private function loadItems(int $quoteId): array
    {
        $stmt = $this->pdo->prepare("SELECT qi.*,p.description AS product_description
            FROM crm_quote_items qi
            LEFT JOIN products p ON p.id=qi.product_id
            WHERE qi.quote_id=? ORDER BY qi.id");
        $stmt->execute(array($quoteId));
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    private function companySettings(): array
    {
        $row = $this->pdo->query('SELECT * FROM system_settings WHERE id=1 LIMIT 1')->fetch(PDO::FETCH_ASSOC);
        return $row ?: array();
    }

    private function documentData(array $quote, array $items, array $company): array
    {
        $customerName = trim((string)($quote['legal_name'] ?: $quote['customer_name']));
        $address = $this->join(array($quote['address'] ?? '', $quote['district'] ?? '', $quote['city'] ?? '', $quote['region'] ?? ''));
        $paymentTerms = $this->paymentTermsLabel($quote['payment_terms'] ?? ($quote['facto_payment_term'] ?? 'contado'));
        $lines = array();
        foreach ($items as $item) {
            $name = trim((string)($item['name'] ?? 'Producto'));
            $sku = trim((string)($item['sku'] ?? ''));
            if (preg_match('/\s*\(SKU:\s*([^)]+)\)\s*$/i', $name, $match)) {
                if ($sku === '' || strtoupper($sku) === 'S/S') $sku = trim($match[1]);
                $name = trim(preg_replace('/\s*\(SKU:\s*[^)]+\)\s*$/i', '', $name));
            }
            $description = trim((string)($item['description'] ?? ''));
            if ($description === '' || preg_match('/^SKU\s*:/i', $description) || $description === $sku) {
                $description = trim((string)($item['product_description'] ?? ''));
            }
            $taxTreatment = strtolower(trim((string)($item['tax_treatment'] ?? '')));
            $taxable = !in_array($taxTreatment, array('exempt', 'exento', 'no_afecto', 'no afecto'), true);
            $lines[] = array(
                'sku' => $sku !== '' && strtoupper($sku) !== 'S/S' ? $sku : '—',
                'name' => $name !== '' ? $name : 'Producto',
                'description' => $description,
                'quantity' => (float)($item['quantity'] ?? 0),
                'unit' => (string)($item['unit'] ?? 'unidad'),
                'unit_price' => (float)($item['price_unit'] ?? 0),
                'taxable' => $taxable,
                'amount' => (float)($item['total_item'] ?? 0),
            );
        }

        $subtotal = (float)($quote['subtotal'] ?? 0);
        $discount = (float)($quote['discount_amount'] ?? 0);
        $net = max(0, $subtotal - $discount);
        $tax = (float)($quote['iva'] ?? 0);
        $total = (float)($quote['total'] ?? ($net + $tax));
        $bankLines = array(
            'Transferencia bancaria:',
            (string)($company['bank_name'] ?? 'Banco Santander'),
            (string)($company['bank_account_type'] ?? 'Cuenta Corriente') . ' · N° ' . (string)($company['bank_account_number'] ?? '000094796822'),
            (string)($company['bank_holder_name'] ?? 'ICYLAB SPA') . ' · RUT: ' . (string)($company['bank_holder_tax_id'] ?? ($company['company_tax_id'] ?? '77.884.104-5')),
            (string)($company['bank_email'] ?? ($company['company_email'] ?? 'contacto@icylab.cl')),
        );
        $leftSections = array(array('title' => 'Formas de pago', 'lines' => $bankLines));
        if (trim((string)($quote['notes'] ?? '')) !== '') {
            $leftSections[] = array('title' => 'Condiciones comerciales', 'text' => (string)$quote['notes']);
        }

        $totals = array(array('label' => 'Subtotal Bruto:', 'value' => $subtotal));
        if ($discount > 0) {
            $label = 'Descuento';
            if ((float)($quote['discount_percent'] ?? 0) > 0) $label .= ' (' . $this->quantity($quote['discount_percent']) . '%)';
            $totals[] = array('label' => $label . ':', 'value' => $discount, 'negative' => true);
        }
        $totals[] = array('label' => 'Monto Neto:', 'value' => $net);
        $totals[] = array('label' => 'Monto Exento:', 'value' => 0, 'hide_when_zero' => true);
        $totals[] = array('label' => 'IVA (19%):', 'value' => $tax);
        $totals[] = array('label' => 'Total General:', 'value' => $total, 'grand' => true);

        return array(
            'company' => $company,
            'document_type' => 'COTIZACIÓN',
            'document_number' => preg_replace('/^COT-/i', '', (string)($quote['quote_number'] ?? 'S/N')),
            'currency' => 'CLP',
            'information_rows' => array(
                array('Razón Social', $customerName ?: '—', 'Fecha', $this->dateText($quote['created_at'] ?? ''), true),
                array(CommercialDocumentPdfRenderer::taxIdentifierLabel($quote['customer_tax_id'] ?? '', $quote['customer_country'] ?? ''), CommercialDocumentPdfRenderer::formatTaxIdentifier($quote['customer_tax_id'] ?? '', $quote['customer_country'] ?? ''), 'Email Cliente', (string)($quote['email'] ?? '—')),
                array('Teléfono', (string)($quote['phone'] ?? '—'), 'Vendedor', (string)($quote['owner_name'] ?? 'ICYLAB')),
                array('Dirección', $address ?: '—', 'Condición de pago', $paymentTerms),
            ),
            'items' => $lines,
            'left_sections' => $leftSections,
            'totals' => $totals,
        );
    }

    private function paymentTermsLabel($value): string
    {
        if (function_exists('icylab_payment_terms_label')) return (string)icylab_payment_terms_label($value);
        $key = strtolower(trim((string)$value));
        $map = array(
            'contado' => 'Contado', 'credito_7' => 'Crédito 7 días', 'credito_15' => 'Crédito 15 días',
            'credito_30' => 'Crédito 30 días', 'credito_45' => 'Crédito 45 días', 'otro' => 'Otra condición',
        );
        return $map[$key] ?? ($key !== '' ? (string)$value : 'Contado');
    }

    private function dateText($value): string
    {
        $timestamp = strtotime((string)$value);
        return $timestamp ? date('d-m-Y', $timestamp) : date('d-m-Y');
    }

    private function join(array $values): string
    {
        return trim(implode(', ', array_filter(array_map(function ($value) { return trim((string)$value); }, $values), function ($value) { return $value !== ''; })));
    }

    private function quantity($value): string
    {
        return rtrim(rtrim(number_format((float)$value, 2, ',', '.'), '0'), ',');
    }

    private function safeFilename(string $name): string
    {
        $clean = preg_replace('/[^A-Za-z0-9_.-]/', '_', $name);
        return $clean !== '' ? $clean : 'cotizacion';
    }
}
