<?php
declare(strict_types=1);

namespace App\Modules\Inventory\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Inventory\Models\Supplier;
use App\Modules\Inventory\Models\PurchaseOrder;
use App\Modules\Inventory\Models\PurchaseOrderItem;
use App\Modules\Inventory\Models\InventoryItem;
use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Services\PurchaseOrderService;

class PurchaseOrderController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'status'       => trim((string) $request->get('status', '')),
            'supplier_id'  => trim((string) $request->get('supplier_id', '')),
            'warehouse_id' => trim((string) $request->get('warehouse_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 = PurchaseOrder::search($filters, 25, $page);

        return $this->view('Inventory.Views.purchase_orders.index', [
            'orders'     => $result['data'],
            'pagination' => $result['pagination'],
            'filters'    => $filters,
            'suppliers'  => Supplier::allActive(),
            'warehouses' => Warehouse::allActive(),
            'statuses'   => PurchaseOrder::getStatuses(),
        ]);
    }

    public function create(Request $request): Response
    {
        return $this->view('Inventory.Views.purchase_orders.form', [
            'suppliers'  => Supplier::allActive(),
            'warehouses' => Warehouse::allActive(),
            'items'      => InventoryItem::allActive(),
        ]);
    }

    public function store(Request $request): Response
    {
        $header = [
            'supplier_id'            => (int) $request->post('supplier_id', 0),
            'warehouse_id'           => (int) $request->post('warehouse_id', 0),
            'expected_delivery_date' => trim((string) $request->post('expected_delivery_date', '')) ?: null,
            'notes'                  => trim((string) $request->post('notes', '')) ?: null,
        ];

        $rawItems = $request->post('items', []);

        if (!is_array($rawItems) || empty($rawItems)) {
            return $this->redirect('/inventory/purchase-orders/create')->withError('يجب إضافة صنف واحد على الأقل');
        }

        $items = [];
        foreach ($rawItems as $raw) {
            $itemId = (int) ($raw['item_id'] ?? 0);
            $qty    = (string) ($raw['quantity_ordered'] ?? '0');
            $price  = (string) ($raw['unit_price'] ?? '0');
            if ($itemId > 0 && bccomp($qty, '0', 3) > 0) {
                $items[] = [
                    'item_id'          => $itemId,
                    'quantity_ordered'  => $qty,
                    'unit_price'       => $price,
                    'notes'            => $raw['notes'] ?? null,
                ];
            }
        }

        try {
            $poId = PurchaseOrderService::createPO($header, $items);
            return $this->redirect('/inventory/purchase-orders/' . $poId)->withSuccess('تم إنشاء أمر الشراء بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/inventory/purchase-orders/create')->withError($e->getMessage());
        }
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $order = $db->selectOne(
            "SELECT po.*, s.`name_ar` as supplier_name, w.`name_ar` as warehouse_name
             FROM `purchase_orders` po
             JOIN `suppliers` s ON s.`id` = po.`supplier_id`
             JOIN `warehouses` w ON w.`id` = po.`warehouse_id`
             WHERE po.`id` = ?",
            [(int) $id]
        );
        if (!$order) {
            return $this->redirect('/inventory/purchase-orders')->withError('أمر الشراء غير موجود');
        }

        $items = PurchaseOrderItem::getForPO((int) $id);

        // Related procurement documents
        $relatedGRNs = $db->select(
            "SELECT `id`, `grn_number`, `status` FROM `goods_received_notes` WHERE `purchase_order_id` = ? AND `is_archived` = 0 ORDER BY `created_at` DESC",
            [(int) $id]
        );
        $relatedInvoices = $db->select(
            "SELECT `id`, `internal_number`, `total_amount`, `status` FROM `vendor_invoices` WHERE `purchase_order_id` = ? AND `is_archived` = 0 ORDER BY `created_at` DESC",
            [(int) $id]
        );

        return $this->view('Inventory.Views.purchase_orders.show', [
            'order'           => $order,
            'items'           => $items,
            'statuses'        => PurchaseOrder::getStatuses(),
            'relatedGRNs'     => $relatedGRNs,
            'relatedInvoices' => $relatedInvoices,
        ]);
    }

    public function submit(Request $request, string $id): Response
    {
        try {
            PurchaseOrderService::submitPO((int) $id);
            return $this->redirect('/inventory/purchase-orders/' . $id)->withSuccess('تم تقديم أمر الشراء للاعتماد');
        } catch (\RuntimeException $e) {
            return $this->redirect('/inventory/purchase-orders/' . $id)->withError($e->getMessage());
        }
    }

    public function approve(Request $request, string $id): Response
    {
        try {
            PurchaseOrderService::approvePO((int) $id);
            return $this->redirect('/inventory/purchase-orders/' . $id)->withSuccess('تم اعتماد أمر الشراء');
        } catch (\RuntimeException $e) {
            return $this->redirect('/inventory/purchase-orders/' . $id)->withError($e->getMessage());
        }
    }

    public function receiveForm(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $order = $db->selectOne(
            "SELECT po.*, s.`name_ar` as supplier_name, w.`name_ar` as warehouse_name
             FROM `purchase_orders` po
             JOIN `suppliers` s ON s.`id` = po.`supplier_id`
             JOIN `warehouses` w ON w.`id` = po.`warehouse_id`
             WHERE po.`id` = ?",
            [(int) $id]
        );
        if (!$order) {
            return $this->redirect('/inventory/purchase-orders')->withError('أمر الشراء غير موجود');
        }

        if (!in_array($order['status'], ['approved', 'partially_received'], true)) {
            return $this->redirect('/inventory/purchase-orders/' . $id)->withError('أمر الشراء ليس في حالة تسمح بالاستلام');
        }

        $items = PurchaseOrderItem::getForPO((int) $id);

        return $this->view('Inventory.Views.purchase_orders.receive', [
            'order' => $order,
            'items' => $items,
        ]);
    }

    public function receive(Request $request, string $id): Response
    {
        $poItemIds       = $request->post('po_item_ids', []);
        $quantitiesRcvd  = $request->post('quantities_received', []);
        $batchNumbers    = $request->post('batch_numbers', []);
        $expiryDates     = $request->post('expiry_dates', []);

        if (!is_array($poItemIds) || empty($poItemIds)) {
            return $this->redirect('/inventory/purchase-orders/' . $id . '/receive')->withError('لا توجد أصناف للاستلام');
        }

        $receivedItems = [];
        foreach ($poItemIds as $i => $poItemId) {
            $qty = $quantitiesRcvd[$i] ?? '0';
            if ((int) $poItemId > 0 && bccomp((string) $qty, '0', 3) > 0) {
                $receivedItems[] = [
                    'po_item_id'        => (int) $poItemId,
                    'quantity_received'  => (string) $qty,
                    'batch_number'      => $batchNumbers[$i] ?? null,
                    'expiry_date'       => $expiryDates[$i] ?? null,
                ];
            }
        }

        try {
            PurchaseOrderService::receivePO((int) $id, $receivedItems);
            return $this->redirect('/inventory/purchase-orders/' . $id)->withSuccess('تم استلام الأصناف وتحديث الأرصدة بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/inventory/purchase-orders/' . $id . '/receive')->withError($e->getMessage());
        }
    }

    public function cancel(Request $request, string $id): Response
    {
        try {
            PurchaseOrderService::cancelPO((int) $id);
            return $this->redirect('/inventory/purchase-orders/' . $id)->withSuccess('تم إلغاء أمر الشراء');
        } catch (\RuntimeException $e) {
            return $this->redirect('/inventory/purchase-orders/' . $id)->withError($e->getMessage());
        }
    }
}
