<?php

declare(strict_types=1);

namespace App\Modules\Reporting\Presentation\Controllers;

use App\Core\Request;
use App\Modules\Reporting\Application\Services\DocumentPrintService;
use App\Services\PrintSettingsService;
use RuntimeException;

final class DocumentPrintController
{
    public function __construct(private ?DocumentPrintService $service = null)
    {
        $this->service ??= new DocumentPrintService();
    }

    public function check(): void { $this->render('check', 'طباعة شيك', 'checks.view', fn($pdo, $id) => $this->service->check($pdo, $id), ['a4']); }
    public function customer(): void { $this->render('customer_card', 'طباعة عميل', 'customers.view', fn($pdo, $id) => $this->service->customer($pdo, $id), ['a4']); }
    public function supplier(): void { $this->render('supplier_card', 'طباعة مورد', 'suppliers.view', fn($pdo, $id) => $this->service->supplier($pdo, $id), ['a4']); }
    public function salesInvoice(): void { $this->render('sales_invoice', 'طباعة فاتورة مبيعات', 'sales.invoices.print', fn($pdo, $id) => $this->service->salesInvoice($pdo, $id), ['a4','receipt']); }
    public function purchaseInvoice(): void { $this->render('purchase_invoice', 'طباعة فاتورة شراء', 'purchases.print', fn($pdo, $id) => $this->service->purchaseInvoice($pdo, $id), ['a4','receipt']); }
    public function purchaseReturn(): void { $this->render('purchase_return', 'طباعة مرتجع شراء', 'purchase_returns.print', fn($pdo, $id) => $this->service->purchaseReturn($pdo, $id), ['a4','receipt']); }
    public function salesReturn(): void { $this->render('sales_return', 'طباعة مرتجع بيع', 'sales_returns.view', fn($pdo, $id) => $this->service->salesReturn($pdo, $id), ['a4','receipt']); }
    public function customerReceipt(): void { $this->render('customer_receipt', 'طباعة سند قبض', 'sales.receipts.print', fn($pdo, $id) => $this->service->customerReceipt($pdo, $id), ['a4','receipt']); }
    public function cashPayment(): void { $this->render('cash_payment', 'طباعة سند صرف', 'cash.payments.print', fn($pdo, $id) => $this->service->cashPayment($pdo, $id), ['a4','receipt']); }
    public function supplierPayment(): void { $this->render('supplier_payment', 'طباعة سند سداد مورد', 'supplier_payments.print', fn($pdo, $id) => $this->service->supplierPayment($pdo, $id), ['a4','receipt']); }
    public function quotation(): void { $this->render('quotation', 'طباعة عرض سعر', 'quotations.print', fn($pdo, $id) => $this->service->quotation($pdo, $id), ['a4']); }

    private function render(string $documentKey, string $titleForChooser, string $permission, callable $loader, array $allowedFormats = ['a4', 'receipt']): void
    {
        require_permission($permission);

        $format = strtolower((string)($_GET['format'] ?? ''));
        $id = (int)($_GET['id'] ?? 0);
        if ($id <= 0) {
            http_response_code(400);
            exit('Invalid');
        }

        $allowedFormats = array_values(array_intersect(['a4', 'receipt'], $allowedFormats));
        if ($allowedFormats === []) {
            $allowedFormats = ['a4'];
        }

        $pdo = db();
        $printSettings = new PrintSettingsService($pdo);
        $preferredFormat = $printSettings->preferredDocumentFormat($documentKey, $allowedFormats);

        if ($format === '') {
            if (count($allowedFormats) === 1) {
                $format = $preferredFormat;
            } else {
                $basePath = Request::path();
                $qs = $_GET;
                $qs['format'] = 'a4';
                $a4Url = $basePath . '?' . http_build_query($qs);
                $receiptUrl = '';
                if (in_array('receipt', $allowedFormats, true)) {
                    $qs['format'] = 'receipt';
                    $receiptUrl = $basePath . '?' . http_build_query($qs);
                }
                print_format_chooser($a4Url, $receiptUrl, $titleForChooser, $preferredFormat);
                return;
            }
        }

        if (!in_array($format, $allowedFormats, true)) {
            $format = $preferredFormat;
        }

        try {
            $data = $loader($pdo, $id);
        } catch (RuntimeException $e) {
            $code = (int)$e->getCode();
            if ($code >= 400 && $code < 600) {
                http_response_code($code);
            } else {
                http_response_code(500);
            }
            exit($e->getMessage());
        }

        $payload = array_merge([
            'title' => $data['title'],
            'meta' => $data['meta'],
            'company' => $data['company'],
            'footer' => $data['footer'],
            'print_template' => $data['print_template'] ?? null,
            'print_format' => $format,
        ], $data['payload']);

        $payload = $printSettings->preparePrintPayload($documentKey, $payload);

        print_view($format, $data['view'], $payload);
    }
}
