<?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,
        ];

        $itemIds    = $request->post('item_ids', []);
        $quantities = $request->post('quantities', []);
        $unitPrices = $request->post('unit_prices', []);
        $itemNotes  = $request->post('item_notes', []);

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

        $items = [];
        foreach ($itemIds as $i => $itemId) {
            $qty   = $quantities[$i] ?? '0';
            $price = $unitPrices[$i] ?? '0';
            if ((int) $itemId > 0 && bccomp((string) $qty, '0', 3) > 0) {
                $items[] = [
                    'item_id'          => (int) $itemId,
                    'quantity_ordered'  => (string) $qty,
                    'unit_price'       => (string) $price,
                    'notes'            => $itemNotes[$i] ?? 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
    {
        $po = PurchaseOrder::find((int) $id);
        if (!$po) {
            return $this->redirect('/inventory/purchase-orders')->withError('أمر الشراء غير موجود');
        }

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

        $db = App::getInstance()->db();
        $supplier = $db->selectOne("SELECT `name_ar`, `code`, `phone`, `email` FROM `suppliers` WHERE `id` = ?", [(int) $po->supplier_id]);

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

    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
    {
        $po = PurchaseOrder::find((int) $id);
        if (!$po) {
            return $this->redirect('/inventory/purchase-orders')->withError('أمر الشراء غير موجود');
        }

        if (!in_array($po->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', [
            'po'    => $po,
            '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());
        }
    }
}
