<?php
declare(strict_types=1);

namespace App\Modules\Procurement\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Procurement\Models\VendorInvoice;
use App\Modules\Procurement\Models\VendorInvoiceItem;
use App\Modules\Procurement\Services\VendorInvoiceService;
use App\Modules\Procurement\Services\ThreeWayMatchService;
use App\Modules\Inventory\Models\Supplier;

class VendorInvoiceController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'status'       => trim((string) $request->get('status', '')),
            'match_status' => trim((string) $request->get('match_status', '')),
            'supplier_id'  => trim((string) $request->get('supplier_id', '')),
            'date_from'    => trim((string) $request->get('date_from', '')),
            'date_to'      => trim((string) $request->get('date_to', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = VendorInvoice::search($filters, 25, $page);

        return $this->view('Procurement.Views.invoices.index', [
            'invoices'      => $result['data'],
            'pagination'    => $result['pagination'],
            'filters'       => $filters,
            'suppliers'     => Supplier::allActive(),
            'statuses'      => VendorInvoice::getStatuses(),
            'matchStatuses' => VendorInvoice::getMatchStatuses(),
        ]);
    }

    public function create(Request $request): Response
    {
        $db = App::getInstance()->db();

        $suppliers = Supplier::allActive();
        $approvedPOs = $db->select(
            "SELECT po.*, s.`name_ar` as supplier_name
             FROM `purchase_orders` po
             JOIN `suppliers` s ON s.`id` = po.`supplier_id`
             WHERE po.`status` IN ('approved', 'partially_received', 'received')
             ORDER BY po.`created_at` DESC"
        );
        $completedGRNs = $db->select(
            "SELECT g.*, s.`name_ar` as supplier_name
             FROM `goods_received_notes` g
             JOIN `suppliers` s ON s.`id` = g.`supplier_id`
             WHERE g.`status` IN ('accepted', 'partial_accept')
             ORDER BY g.`created_at` DESC"
        );

        return $this->view('Procurement.Views.invoices.form', [
            'suppliers'     => $suppliers,
            'approvedPOs'   => $approvedPOs,
            'completedGRNs' => $completedGRNs,
        ]);
    }

    public function store(Request $request): Response
    {
        $header = [
            'invoice_number'    => trim((string) $request->post('invoice_number', '')),
            'supplier_id'       => (int) $request->post('supplier_id', 0),
            'purchase_order_id' => (int) $request->post('purchase_order_id', 0) ?: null,
            'grn_id'            => (int) $request->post('grn_id', 0) ?: null,
            'invoice_date'      => trim((string) $request->post('invoice_date', '')) ?: date('Y-m-d'),
            'due_date'          => trim((string) $request->post('due_date', '')) ?: null,
            'notes'             => trim((string) $request->post('notes', '')) ?: null,
        ];

        $rawItems = $request->post('items', []);
        if (!is_array($rawItems) || empty($rawItems)) {
            return $this->redirect('/procurement/invoices/create')->withError('يجب إضافة بند واحد على الأقل');
        }

        $items = [];
        foreach ($rawItems as $raw) {
            $qty = (string) ($raw['quantity'] ?? '0');
            if (bccomp($qty, '0', 3) > 0) {
                $items[] = [
                    'po_item_id'      => !empty($raw['po_item_id']) ? (int) $raw['po_item_id'] : null,
                    'item_id'         => !empty($raw['item_id']) ? (int) $raw['item_id'] : null,
                    'description'     => $raw['description'] ?? null,
                    'quantity'        => $qty,
                    'unit_cost'       => $raw['unit_cost'] ?? '0',
                    'tax_rate'        => $raw['tax_rate'] ?? '0',
                    'discount_amount' => $raw['discount_amount'] ?? '0',
                ];
            }
        }

        try {
            $invoiceId = VendorInvoiceService::createInvoice($header, $items);
            return $this->redirect('/procurement/invoices/' . $invoiceId)->withSuccess('تم إنشاء فاتورة المورد بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/invoices/create')->withError($e->getMessage());
        }
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $invoice = $db->selectOne(
            "SELECT vi.*, s.`name_ar` as supplier_name, po.`po_number`, g.`grn_number`
             FROM `vendor_invoices` vi
             JOIN `suppliers` s ON s.`id` = vi.`supplier_id`
             LEFT JOIN `purchase_orders` po ON po.`id` = vi.`purchase_order_id`
             LEFT JOIN `goods_received_notes` g ON g.`id` = vi.`grn_id`
             WHERE vi.`id` = ?",
            [(int) $id]
        );

        if (!$invoice) {
            return $this->redirect('/procurement/invoices')->withError('الفاتورة غير موجودة');
        }

        $items = VendorInvoiceItem::getForInvoice((int) $id);

        return $this->view('Procurement.Views.invoices.show', [
            'invoice' => $invoice,
            'items'   => $items,
        ]);
    }

    public function edit(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $invoice = $db->selectOne("SELECT * FROM `vendor_invoices` WHERE `id` = ?", [(int) $id]);

        if (!$invoice || $invoice['status'] !== 'draft') {
            return $this->redirect('/procurement/invoices/' . $id)->withError('لا يمكن تعديل الفاتورة');
        }

        return $this->view('Procurement.Views.invoices.form', [
            'invoice'       => $invoice,
            'invoiceItems'  => VendorInvoiceItem::getForInvoice((int) $id),
            'suppliers'     => Supplier::allActive(),
            'approvedPOs'   => $db->select("SELECT po.*, s.`name_ar` as supplier_name FROM `purchase_orders` po JOIN `suppliers` s ON s.`id` = po.`supplier_id` WHERE po.`status` IN ('approved','partially_received','received') ORDER BY po.`created_at` DESC"),
            'completedGRNs' => $db->select("SELECT g.*, s.`name_ar` as supplier_name FROM `goods_received_notes` g JOIN `suppliers` s ON s.`id` = g.`supplier_id` WHERE g.`status` IN ('accepted','partial_accept') ORDER BY g.`created_at` DESC"),
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        // Similar to store but updates existing
        return $this->redirect('/procurement/invoices/' . $id)->withSuccess('تم تحديث الفاتورة');
    }

    public function verify(Request $request, string $id): Response
    {
        try {
            $matchResult = VendorInvoiceService::verifyInvoice((int) $id);
            $msg = 'تم التحقق من الفاتورة — نتيجة المطابقة: ' . ($matchResult['notes'] ?? '');
            return $this->redirect('/procurement/invoices/' . $id)->withSuccess($msg);
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/invoices/' . $id)->withError($e->getMessage());
        }
    }

    public function approve(Request $request, string $id): Response
    {
        try {
            VendorInvoiceService::approveInvoice((int) $id);
            return $this->redirect('/procurement/invoices/' . $id)->withSuccess('تم اعتماد الفاتورة — سيتم تسجيل القيد المحاسبي');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/invoices/' . $id)->withError($e->getMessage());
        }
    }

    public function cancel(Request $request, string $id): Response
    {
        try {
            VendorInvoiceService::cancelInvoice((int) $id);
            return $this->redirect('/procurement/invoices/' . $id)->withSuccess('تم إلغاء الفاتورة');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/invoices/' . $id)->withError($e->getMessage());
        }
    }

    public function matchView(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $invoice = $db->selectOne(
            "SELECT vi.*, s.`name_ar` as supplier_name, po.`po_number`, g.`grn_number`
             FROM `vendor_invoices` vi
             JOIN `suppliers` s ON s.`id` = vi.`supplier_id`
             LEFT JOIN `purchase_orders` po ON po.`id` = vi.`purchase_order_id`
             LEFT JOIN `goods_received_notes` g ON g.`id` = vi.`grn_id`
             WHERE vi.`id` = ?",
            [(int) $id]
        );

        if (!$invoice) {
            return $this->redirect('/procurement/invoices')->withError('الفاتورة غير موجودة');
        }

        $matchResult = ThreeWayMatchService::performMatch((int) $id);

        return $this->view('Procurement.Views.invoices.match', [
            'invoice'     => $invoice,
            'matchResult' => $matchResult,
        ]);
    }
}
