<?php

class InvoiceController extends Controller
{
    private Invoice $invoices;
    private Broker $brokers;

    public function __construct()
    {
        $this->invoices = new Invoice();
        $this->brokers = new Broker();
    }

    public function index(): void
    {
        Auth::requireRole(['owner', 'admin', 'dispatcher', 'accountant']);
        $search = trim($_GET['search'] ?? '');
        $invoices = $this->invoices->all($search ?: null);
        $this->view('invoices/index', compact('invoices', 'search'));
        clear_old();
    }

    public function create(): void
    {
        Auth::requireRole(['owner', 'admin', 'accountant']);
        $invoice = null;
        $loads = $this->invoices->openLoads();
        $brokers = $this->brokers->active();
        $statuses = Invoice::STATUSES;
        $nextNumber = $this->invoices->nextNumber();
        $selectedLoad = null;
        if (!empty($_GET['load_id'])) {
            foreach ($loads as $load) {
                if ((int) $load['id'] === (int) $_GET['load_id']) {
                    $selectedLoad = $load;
                    break;
                }
            }
        }
        $this->view('invoices/create', compact('invoice', 'loads', 'brokers', 'statuses', 'nextNumber', 'selectedLoad'));
    }

    public function store(): void
    {
        Auth::requireRole(['owner', 'admin', 'accountant']);
        Csrf::verify();
        if (empty(trim($_POST['invoice_number'] ?? ''))) {
            set_old($_POST);
            $this->flash('danger', 'Invoice number is required.');
            $this->redirect('/invoices/create');
        }
        $id = $this->invoices->create($_POST);
        (new Accounting())->postInvoice($id);
        log_activity('invoice_created', 'Created invoice ' . trim($_POST['invoice_number']));
        $this->flash('success', 'Invoice created successfully.');
        $this->redirect('/invoices/view?id=' . $id);
    }

    public function edit(): void
    {
        Auth::requireRole(['owner', 'admin', 'accountant']);
        $invoice = $this->invoices->find((int) ($_GET['id'] ?? 0));
        if (!$invoice) {
            $this->flash('danger', 'Invoice not found.');
            $this->redirect('/invoices');
        }
        $loads = $this->invoices->openLoads();
        $brokers = $this->brokers->active();
        $statuses = Invoice::STATUSES;
        $nextNumber = $invoice['invoice_number'];
        $selectedLoad = null;
        $this->view('invoices/edit', compact('invoice', 'loads', 'brokers', 'statuses', 'nextNumber', 'selectedLoad'));
    }

    public function update(): void
    {
        Auth::requireRole(['owner', 'admin', 'accountant']);
        Csrf::verify();
        $id = (int) ($_POST['id'] ?? 0);
        if (!$id || empty(trim($_POST['invoice_number'] ?? ''))) {
            set_old($_POST);
            $this->flash('danger', 'Invoice number is required.');
            $this->redirect('/invoices/edit?id=' . $id);
        }
        $this->invoices->update($id, $_POST);
        (new Accounting())->postInvoice($id);
        log_activity('invoice_updated', 'Updated invoice ' . trim($_POST['invoice_number']));
        $this->flash('success', 'Invoice updated successfully.');
        $this->redirect('/invoices/view?id=' . $id);
    }

    public function viewInvoice(): void
    {
        Auth::requireRole(['owner', 'admin', 'dispatcher', 'accountant']);
        $invoice = $this->invoices->find((int) ($_GET['id'] ?? 0));
        if (!$invoice) {
            $this->flash('danger', 'Invoice not found.');
            $this->redirect('/invoices');
        }
        $this->view('invoices/view', compact('invoice'));
    }

    public function addPayment(): void
    {
        Auth::requireRole(['owner', 'admin', 'accountant']);
        Csrf::verify();
        $id = (int) ($_POST['invoice_id'] ?? 0);
        $this->invoices->addPayment($id, $_POST);
        (new Accounting())->postPayment($id, (float) ($_POST['amount'] ?? 0), $_POST['payment_date'] ?: date('Y-m-d'));
        log_activity('payment_added', 'Added invoice payment');
        $this->flash('success', 'Payment saved successfully.');
        $this->redirect('/invoices/view?id=' . $id);
    }

    public function status(): void
    {
        Auth::requireRole(['owner', 'admin', 'accountant']);
        Csrf::verify();
        $id = (int) ($_POST['id'] ?? 0);
        $this->invoices->markStatus($id, $_POST['status'] ?? 'draft');
        (new Accounting())->postInvoice($id);
        log_activity('invoice_status_updated', 'Updated invoice status');
        $this->flash('success', 'Invoice status updated.');
        $this->redirect('/invoices/view?id=' . $id);
    }

    public function delete(): void
    {
        Auth::requireRole(['owner', 'admin', 'accountant']);
        Csrf::verify();
        $id = (int) ($_POST['id'] ?? 0);
        $invoice = $this->invoices->find($id);
        if (!$invoice) {
            $this->flash('danger', 'Invoice not found.');
            $this->redirect('/invoices');
        }
        if ($invoice['status'] !== 'draft' || !empty($invoice['payments'])) {
            $this->flash('danger', 'Only unpaid draft invoices can be deleted. Use Void for posted invoices.');
            $this->redirect('/invoices/view?id=' . $id);
        }
        $this->invoices->delete($id);
        log_activity('invoice_deleted', 'Deleted draft invoice ' . $invoice['invoice_number']);
        $this->flash('success', 'Draft invoice deleted successfully.');
        $this->redirect('/invoices');
    }

    public function pdf(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','accountant']);
        $invoice=$this->invoices->find((int)($_GET['id']??0));
        if(!$invoice){$this->flash('danger','Invoice not found.');$this->redirect('/invoices');}
        $pdf=new SimplePdf();
        $company=setting('company_name',APP_NAME)?:APP_NAME;
        $pdf->rect(36,706,540,58,true,0.93);
        $companyX=50;
        $logoRelative=setting('company_logo','');
        if($logoRelative&&$pdf->image(base_path($logoRelative),50,714,50,42))$companyX=112;
        $pdf->text($companyX,742,$company,18,true);
        $pdf->text($companyX,725,trim((setting('company_address','')?:'').'  '.(setting('company_phone','')?:'')),8);
        $pdf->text(440,742,'INVOICE',20,true);
        $pdf->text(440,724,$invoice['invoice_number'],10,true);
        $pdf->text(40,681,'BILL TO',9,true);$pdf->line(40,676,290,676);
        $pdf->text(320,681,'INVOICE DETAILS',9,true);$pdf->line(320,676,572,676);
        $pdf->text(45,658,$invoice['broker_name']?:'-',11,true);
        $y=$pdf->wrappedText(45,642,$invoice['broker_address']?:'',235,8,11,false,3);
        $pdf->text(45,$y,$invoice['broker_email']?:'',8);
        $pdf->text(325,658,'Invoice date',8,true);$pdf->text(440,658,date_display($invoice['invoice_date']?:$invoice['created_at']),8);
        $pdf->text(325,642,'Due date',8,true);$pdf->text(440,642,date_display($invoice['due_date']),8);
        $pdf->text(325,626,'Status',8,true);$pdf->text(440,626,readable_status($invoice['status']),8);
        $pdf->text(325,610,'Load / Reference',8,true);$pdf->text(440,610,($invoice['load_number']?:'-').' / '.($invoice['reference_number']?:'-'),8);
        $pdf->rect(40,530,532,64,false);
        $pdf->text(50,575,'LOAD DETAILS',9,true);
        $pdf->text(50,558,'Pickup',8,true);$pdf->wrappedText(95,558,$invoice['pickup_location']?:'-',185,8,10,false,2);
        $pdf->text(300,558,'Delivery',8,true);$pdf->wrappedText(350,558,$invoice['delivery_location']?:'-',210,8,10,false,2);
        $pdf->text(50,538,'Driver / Equipment',8,true);$pdf->text(145,538,($invoice['driver_name']?:'-').' / '.($invoice['unit_number']?:'-').' / '.($invoice['trailer_number']?:'-'),8);
        $pdf->rect(40,492,532,24,true,0.92);$pdf->text(48,500,'DESCRIPTION',9,true);$pdf->text(500,500,'AMOUNT',9,true);
        $y=474;foreach(array_slice($invoice['items'],0,8) as$item){$pdf->text(48,$y,$item['description'],9);$pdf->text(500,$y,money($item['amount']),9);$pdf->line(40,$y-7,572,$y-7,0.3);$y-=22;}
        $summaryY=max(160,$y-5);$pdf->text(400,$summaryY,'Subtotal',9);$pdf->text(500,$summaryY,money($invoice['subtotal']),9);$summaryY-=18;
        if((float)$invoice['tax']!=0){$pdf->text(400,$summaryY,'Tax',9);$pdf->text(500,$summaryY,money($invoice['tax']),9);$summaryY-=18;}
        if((float)$invoice['discount']!=0){$pdf->text(400,$summaryY,'Discount',9);$pdf->text(500,$summaryY,'- '.money($invoice['discount']),9);$summaryY-=18;}
        if((float)$invoice['deductions']!=0){$pdf->text(400,$summaryY,'Deductions',9);$pdf->text(500,$summaryY,'- '.money($invoice['deductions']),9);$summaryY-=18;}
        $pdf->line(395,$summaryY+8,572,$summaryY+8);$pdf->text(400,$summaryY-6,'TOTAL',11,true);$pdf->text(500,$summaryY-6,money($invoice['total']),11,true);$summaryY-=27;$pdf->text(400,$summaryY,'Balance due',10,true);$pdf->text(500,$summaryY,money($invoice['balance_due']),10,true);
        $pdf->text(40,120,'PAYMENT INSTRUCTIONS',9,true);$pdf->wrappedText(40,104,setting('invoice_payment_instructions','Please remit payment using the agreed payment method.')?:'',330,8,11,false,4);
        $pdf->text(40,55,setting('invoice_terms','Thank you for your business.')?:'',8);$pdf->text(500,35,'Page 1 of 1',7);
        $out=$pdf->output();header('Content-Type: application/pdf');header('Content-Disposition: attachment; filename="'.preg_replace('/[^A-Za-z0-9_-]/','_',$invoice['invoice_number']).'.pdf"');header('Content-Length: '.strlen($out));echo$out;exit;
    }

    public function paymentReceipt(): void
    {
        Auth::requireRole(['owner','admin','accountant','dispatcher']);
        $paymentId=(int)($_GET['id']??0);
        $stmt=Database::connection()->prepare('SELECT payments.*,invoices.invoice_number,invoices.total,invoices.broker_id,brokers.company_name broker_name,brokers.address broker_address,loads.load_number FROM payments JOIN invoices ON invoices.id=payments.invoice_id LEFT JOIN brokers ON brokers.id=invoices.broker_id LEFT JOIN loads ON loads.id=invoices.load_id WHERE payments.id=?');
        $stmt->execute([$paymentId]);$payment=$stmt->fetch();
        if(!$payment){$this->flash('danger','Payment receipt not found.');$this->redirect('/invoices');}
        $pdf=new SimplePdf();$pdf->rect(36,706,540,58,true,0.93);$companyX=50;$logoRelative=setting('company_logo','');if($logoRelative&&$pdf->image(base_path($logoRelative),50,714,50,42))$companyX=112;$pdf->text($companyX,742,setting('company_name',APP_NAME)?:APP_NAME,18,true);$pdf->text($companyX,725,trim((setting('company_address','')?:'').'  '.(setting('company_phone','')?:'')),8);$pdf->text(420,742,'PAYMENT RECEIPT',15,true);$pdf->text(475,724,'RCPT-'.str_pad((string)$paymentId,6,'0',STR_PAD_LEFT),9,true);
        $pdf->text(40,675,'RECEIVED FROM',9,true);$pdf->line(40,670,285,670);$pdf->text(45,648,$payment['broker_name']?:'Customer',12,true);$pdf->wrappedText(45,630,$payment['broker_address']?:'',225,8,11,false,3);
        $pdf->text(320,675,'PAYMENT DETAILS',9,true);$pdf->line(320,670,572,670);foreach([['Payment date',date_display($payment['payment_date'])],['Invoice',$payment['invoice_number']],['Load',$payment['load_number']?:'-'],['Method',$payment['method']?:'-'],['Reference',$payment['reference']?:'-']] as$i=>$row){$y=648-$i*20;$pdf->text(325,$y,$row[0],8,true);$pdf->text(430,$y,$row[1],8);}
        $pdf->rect(40,490,532,82,true,0.95);$pdf->text(58,540,'AMOUNT RECEIVED',12,true);$pdf->text(410,532,money($payment['amount']),24,true);$pdf->text(58,515,'Applied to invoice '.$payment['invoice_number'],9);
        $pdf->text(40,420,'NOTES',9,true);$pdf->line(40,414,572,414);$pdf->wrappedText(45,392,$payment['notes']?:'Payment received and recorded.',510,9,13,false,6);
        $pdf->text(40,85,'Thank you. This receipt confirms the payment shown above.',9);$pdf->line(360,110,572,110);$pdf->text(360,95,'Authorized acknowledgement',8);$pdf->text(500,35,'Page 1 of 1',7);
        $out=$pdf->output();header('Content-Type: application/pdf');header('Content-Disposition: attachment; filename="receipt-'.$paymentId.'.pdf"');header('Content-Length: '.strlen($out));echo$out;exit;
    }


}