<?php
declare(strict_types=1);

namespace App\Helpers;

use Mpdf\Mpdf;
use Exception;

class PDFHelper
{
    private static function getMpdf(): Mpdf
    {
        return new Mpdf([
            'mode' => 'utf-8',
            'format' => 'A4',
            'margin_left' => 15,
            'margin_right' => 15,
            'margin_top' => 16,
            'margin_bottom' => 16,
            'margin_header' => 9,
            'margin_footer' => 9,
            'default_font' => 'helvetica' // Standard font for safety
        ]);
    }

    private static function parseTemplate(array $invoice, array $tenant, string $template = 'classic'): string
    {
        $templatePath = __DIR__ . '/../templates/' . $template . '_template.html';
        if (!file_exists($templatePath)) {
            $templatePath = __DIR__ . '/../templates/classic_template.html';
        }
        
        if (!file_exists($templatePath)) {
            throw new Exception("PDF template not found at {$templatePath}");
        }

        $html = file_get_contents($templatePath);
        
        $docType = $invoice['invoice_type'] ?? 'Tax Invoice';
        if (isset($invoice['cn_number'])) $docType = 'Credit Note';
        if (isset($invoice['dn_number'])) $docType = 'Debit Note';
        if (isset($invoice['po_number']) && !isset($invoice['invoice_number'])) $docType = 'Purchase Order';
        
        $docNumber = $invoice['invoice_number'] ?? $invoice['cn_number'] ?? $invoice['dn_number'] ?? $invoice['po_number'] ?? 'N/A';
        $docDate = $invoice['invoice_date'] ?? $invoice['cn_date'] ?? $invoice['dn_date'] ?? $invoice['po_date'] ?? date('Y-m-d');

        // Logo handling
        $logoPath = $tenant['logo'] ?? '';
        $logoHtml = '';
        if ($logoPath) {
            $absPath = __DIR__ . '/../../' . $logoPath;
            if (file_exists($absPath)) {
                $logoHtml = '<img src="' . $absPath . '" style="max-height: 80px; max-width: 200px;">';
            }
        }

        // Prepare variables map
        $vars = [
            '{{COMPANY_NAME}}' => htmlspecialchars($tenant['business_name'] ?? $tenant['company_name'] ?? 'Your Company Name'),
            '{{COMPANY_ADDRESS}}' => nl2br(htmlspecialchars($tenant['address'] ?? '')),
            '{{COMPANY_GSTIN}}' => htmlspecialchars($tenant['gstin'] ?? '-'),
            '{{COMPANY_EMAIL}}' => htmlspecialchars($tenant['email'] ?? ''),
            '{{COMPANY_PHONE}}' => htmlspecialchars($tenant['phone'] ?? ''),
            '{{COMPANY_LOGO}}' => $logoHtml,
            
            '{{DOCUMENT_TITLE}}' => strtoupper(str_replace('_', ' ', (string)$docType)),
            '{{INVOICE_NUMBER}}' => htmlspecialchars((string)$docNumber),
            '{{INVOICE_DATE}}' => date('d-M-Y', strtotime((string)$docDate)),
            '{{DUE_DATE}}' => !empty($invoice['due_date']) ? date('d-M-Y', strtotime((string)$invoice['due_date'])) : '-',
            '{{PO_NUMBER}}' => htmlspecialchars($invoice['po_number'] ?? '-'),
            '{{PLACE_OF_SUPPLY}}' => htmlspecialchars($invoice['place_of_supply'] ?? '-'),
            
            '{{CUSTOMER_NAME}}' => htmlspecialchars($invoice['company_name'] ?? $invoice['customer_name'] ?? $invoice['vendor_name'] ?? 'Walk-in'),
            '{{CUSTOMER_GSTIN}}' => htmlspecialchars($invoice['customer_gstin'] ?? $invoice['vendor_gstin'] ?? '-'),
            '{{BILLING_ADDRESS}}' => nl2br(htmlspecialchars($invoice['billing_address'] ?? '')),
            '{{SHIPPING_ADDRESS}}' => nl2br(htmlspecialchars($invoice['shipping_address'] ?? $invoice['delivery_address'] ?? 'Same as Billing')),
            
            '{{SUBTOTAL}}' => number_format((float)($invoice['subtotal'] ?? 0), 2),
            '{{DISCOUNT_AMOUNT}}' => number_format((float)($invoice['discount_amount'] ?? 0), 2),
            '{{TAXABLE_AMOUNT}}' => number_format((float)($invoice['taxable_amount'] ?? 0), 2),
            '{{TOTAL_TAX}}' => number_format((float)($invoice['total_tax'] ?? 0), 2),
            '{{GRAND_TOTAL}}' => number_format((float)($invoice['grand_total'] ?? 0), 2),
            '{{AMOUNT_PAID}}' => number_format((float)($invoice['amount_paid'] ?? 0), 2),
            '{{BALANCE_DUE}}' => number_format((float)($invoice['balance_due'] ?? 0), 2),
            '{{ROUND_OFF}}' => number_format((float)($invoice['round_off'] ?? 0), 2),
            
            '{{AMOUNT_IN_WORDS}}' => ucfirst(InvoiceHelper::amountToWords((float)($invoice['grand_total'] ?? 0)) . ' Only'),
            '{{NOTES}}' => nl2br(htmlspecialchars($invoice['notes'] ?? '')),
            '{{TERMS}}' => nl2br(htmlspecialchars($invoice['terms'] ?? '')),
            '{{WATERMARK}}' => ''
        ];

        // Format Items properly
        $itemsHtml = '';
        foreach ($invoice['items'] ?? [] as $i => $item) {
            if ($template === 'modern_green') {
                $descParts = explode("\n", htmlspecialchars($item['description']));
                $name = array_shift($descParts);
                $desc = implode("<br>", $descParts);
                
                $itemsHtml .= "<tr>";
                $itemsHtml .= "<td>".($i+1)."</td>";
                $itemsHtml .= "<td><span style='font-weight:bold; font-size:11pt;'>$name</span><br><span style='font-size:9pt; color:#666;'>$desc</span></td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)$item['quantity'], 2)."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)$item['unit_price'], 2)."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)$item['total_amount'], 2)."</td>";
                $itemsHtml .= "</tr>";
            } else {
                $itemsHtml .= "<tr>";
                $itemsHtml .= "<td style='text-align:center;'>".($i+1)."</td>";
                $itemsHtml .= "<td>".htmlspecialchars($item['description'] ?? '')."</td>";
                $itemsHtml .= "<td>".htmlspecialchars($item['hsn_code'] ?? '')."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)($item['quantity'] ?? 0), 2)." ".($item['unit'] ?? '')."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)($item['unit_price'] ?? 0), 2)."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)($item['discount_amount'] ?? 0), 2)."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)($item['taxable_amount'] ?? 0), 2)."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)($item['tax_rate'] ?? 0), 2)."%</td>";
                $totalTax = (float)(($item['cgst_amount'] ?? 0) + ($item['sgst_amount'] ?? 0) + ($item['igst_amount'] ?? 0));
                $itemsHtml .= "<td style='text-align:right;'>".number_format($totalTax, 2)."</td>";
                $itemsHtml .= "<td style='text-align:right;'>".number_format((float)($item['total_amount'] ?? 0), 2)."</td>";
                $itemsHtml .= "</tr>";
            }
        }
        $vars['{{ITEMS_ROWS}}'] = $itemsHtml;

        // GST Summary Formatting
        $gstSummaryHtml = '';
        $isInterstate = (int)($invoice['is_interstate'] ?? 0) === 1;
        
        $itemRates = [];
        foreach ($invoice['items'] ?? [] as $item) {
            $rate = (string)(float)$item['tax_rate'];
            if (!isset($itemRates[$rate])) {
                $itemRates[$rate] = ['taxable' => 0, 'cgst' => 0, 'sgst' => 0, 'igst' => 0, 'cess' => 0];
            }
            $itemRates[$rate]['taxable'] += (float)$item['taxable_amount'];
            $itemRates[$rate]['cgst'] += (float)$item['cgst_amount'];
            $itemRates[$rate]['sgst'] += (float)$item['sgst_amount'];
            $itemRates[$rate]['igst'] += (float)$item['igst_amount'];
            $itemRates[$rate]['cess'] += (float)$item['cess_amount'];
        }

        $simpleTaxSummary = '';
        foreach ($itemRates as $rate => $taxes) {
            $gstSummaryHtml .= "<tr>";
            $gstSummaryHtml .= "<td>$rate%</td>";
            $gstSummaryHtml .= "<td style='text-align:right;'>".number_format($taxes['taxable'], 2)."</td>";
            if ($isInterstate) {
                $gstSummaryHtml .= "<td>-</td><td>-</td><td style='text-align:right;'>".number_format($taxes['igst'], 2)."</td>";
            } else {
                $gstSummaryHtml .= "<td style='text-align:right;'>".number_format($taxes['cgst'], 2)."</td><td style='text-align:right;'>".number_format($taxes['sgst'], 2)."</td><td>-</td>";
            }
            $gstSummaryHtml .= "<td style='text-align:right;'>".number_format($taxes['cess'], 2)."</td>";
            $totalTaxRow = $taxes['cgst'] + $taxes['sgst'] + $taxes['igst'] + $taxes['cess'];
            $gstSummaryHtml .= "<td style='text-align:right;'>".number_format($totalTaxRow, 2)."</td>";
            $gstSummaryHtml .= "</tr>";
            
            if ($simpleTaxSummary !== '') $simpleTaxSummary .= ', ';
            $simpleTaxSummary .= "$rate%";
        }
        
        $vars['{{GST_SUMMARY_ROWS}}'] = $gstSummaryHtml ?: "<tr><td colspan='7' style='text-align:center;'>No taxes applied</td></tr>";
        $vars['{{TAX_SUMMARY_SIMPLE}}'] = $simpleTaxSummary ?: '0.00%';
        $vars['{{SUBTOTAL}}'] = number_format((float)$invoice['subtotal'], 2);
        $vars['{{TOTAL_TAX}}'] = number_format((float)$invoice['total_tax'], 2);
        $vars['{{DISCOUNT_AMOUNT}}'] = number_format((float)($invoice['discount_amount'] ?? 0), 2);
        $vars['{{GRAND_TOTAL}}'] = number_format((float)$invoice['grand_total'], 2);
        $vars['{{BALANCE_DUE}}'] = number_format((float)$invoice['balance_due'], 2);
        $vars['{{TOTAL_IN_WORDS}}'] = $vars['{{AMOUNT_IN_WORDS}}'];

        if ($invoice['status'] === 'draft') {
            $vars['{{WATERMARK}}'] = '<div style="position: absolute; top:35%; left:25%; font-size:100pt; color:rgba(200,200,200,0.3); transform:rotate(-45deg);">DRAFT</div>';
        } elseif ($invoice['status'] === 'cancelled') {
            $vars['{{WATERMARK}}'] = '<div style="position: absolute; top:35%; left:15%; font-size:90pt; color:rgba(255,100,100,0.3); transform:rotate(-45deg);">CANCELLED</div>';
        }

        // Apply
        return str_replace(array_keys($vars), array_values($vars), $html);
    }

    public static function generate(array $invoice, array $tenant, string $template = 'classic'): string
    {
        $html = self::parseTemplate($invoice, $tenant, $template);
        $mpdf = self::getMpdf();
        $mpdf->WriteHTML($html);
        
        $filename = "invoice_{$invoice['id']}_" . str_replace('/', '_', $invoice['invoice_number']) . ".pdf";
        $dir = __DIR__ . '/../../tmp/invoices';
        if (!is_dir($dir)) mkdir($dir, 0777, true);
        
        $path = $dir . '/' . $filename;
        $mpdf->Output($path, \Mpdf\Output\Destination::FILE);
        
        return $path;
    }

    public static function stream(array $invoice, array $tenant, string $template = 'classic'): void
    {
        // Suppress warnings that might corrupt the PDF stream
        error_reporting(0);
        ini_set('display_errors', '0');
        
        $html = self::parseTemplate($invoice, $tenant, $template);
        $mpdf = self::getMpdf();
        $mpdf->WriteHTML($html);
        $docNumber = $invoice['invoice_number'] ?? $invoice['cn_number'] ?? $invoice['dn_number'] ?? $invoice['po_number'] ?? 'document';
        $filename = str_replace(['/', '\\', ' '], '_', $docNumber) . ".pdf";
        $mpdf->Output($filename, \Mpdf\Output\Destination::INLINE);
        exit;
    }

    public static function downloadBase64(array $invoice, array $tenant, string $template = 'classic'): string
    {
        $html = self::parseTemplate($invoice, $tenant, $template);
        $mpdf = self::getMpdf();
        $mpdf->WriteHTML($html);
        $pdfContent = $mpdf->Output('', \Mpdf\Output\Destination::STRING_RETURN);
        return base64_encode($pdfContent);
    }
}
