<?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\GoodsReceivedNote;
use App\Modules\Procurement\Models\GrnItem;
use App\Modules\Procurement\Services\GoodsReceivingService;
use App\Modules\Inventory\Models\Supplier;
use App\Modules\Inventory\Models\Warehouse;

class GoodsReceivedNoteController 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 = GoodsReceivedNote::search($filters, 25, $page);

        return $this->view('Procurement.Views.grn.index', [
            'grns'       => $result['data'],
            'pagination' => $result['pagination'],
            'filters'    => $filters,
            'suppliers'  => Supplier::allActive(),
            'warehouses' => Warehouse::allActive(),
            'statuses'   => GoodsReceivedNote::getStatuses(),
        ]);
    }

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

        // Get POs that can receive goods
        $openPOs = $db->select(
            "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.`status` IN ('approved', 'partially_received')
             ORDER BY po.`created_at` DESC"
        );

        return $this->view('Procurement.Views.grn.form', [
            'openPOs' => $openPOs,
        ]);
    }

    public function store(Request $request): Response
    {
        $poId = (int) $request->post('purchase_order_id', 0);

        $header = [
            'received_date' => trim((string) $request->post('received_date', '')) ?: null,
            'notes'         => trim((string) $request->post('notes', '')) ?: null,
        ];

        $rawItems = $request->post('items', []);
        if (!is_array($rawItems) || empty($rawItems)) {
            return $this->redirect('/procurement/grn/create')->withError('يجب تحديد أصناف مستلمة');
        }

        $receivedItems = [];
        foreach ($rawItems as $raw) {
            $poItemId = (int) ($raw['po_item_id'] ?? 0);
            $qty = (string) ($raw['quantity_received'] ?? '0');
            if ($poItemId > 0 && bccomp($qty, '0', 3) > 0) {
                $receivedItems[] = [
                    'po_item_id'        => $poItemId,
                    'quantity_received' => $qty,
                    'batch_number'      => $raw['batch_number'] ?? null,
                    'expiry_date'       => $raw['expiry_date'] ?? null,
                    'notes'             => $raw['notes'] ?? null,
                ];
            }
        }

        try {
            $grnId = GoodsReceivingService::createGRN($poId, $receivedItems, $header);
            return $this->redirect('/procurement/grn/' . $grnId)->withSuccess('تم إنشاء إذن الاستلام بنجاح — يرجى إجراء الفحص');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/grn/create')->withError($e->getMessage());
        }
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $grn = $db->selectOne(
            "SELECT g.*, s.`name_ar` as supplier_name, w.`name_ar` as warehouse_name,
                    po.`po_number`, e.`full_name_ar` as receiver_name
             FROM `goods_received_notes` g
             JOIN `suppliers` s ON s.`id` = g.`supplier_id`
             JOIN `warehouses` w ON w.`id` = g.`warehouse_id`
             LEFT JOIN `purchase_orders` po ON po.`id` = g.`purchase_order_id`
             LEFT JOIN `employees` e ON e.`id` = g.`received_by`
             WHERE g.`id` = ?",
            [(int) $id]
        );

        if (!$grn) {
            return $this->redirect('/procurement/grn')->withError('إذن الاستلام غير موجود');
        }

        $items = GrnItem::getForGRN((int) $id);

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

    public function inspectForm(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $grn = $db->selectOne(
            "SELECT g.*, s.`name_ar` as supplier_name, w.`name_ar` as warehouse_name,
                    po.`po_number`
             FROM `goods_received_notes` g
             JOIN `suppliers` s ON s.`id` = g.`supplier_id`
             JOIN `warehouses` w ON w.`id` = g.`warehouse_id`
             LEFT JOIN `purchase_orders` po ON po.`id` = g.`purchase_order_id`
             WHERE g.`id` = ?",
            [(int) $id]
        );

        if (!$grn) {
            return $this->redirect('/procurement/grn')->withError('إذن الاستلام غير موجود');
        }

        if (!in_array($grn['status'], ['draft', 'inspecting'], true)) {
            return $this->redirect('/procurement/grn/' . $id)->withError('إذن الاستلام ليس في حالة تسمح بالفحص');
        }

        $items = GrnItem::getForGRN((int) $id);

        return $this->view('Procurement.Views.grn.inspect', [
            'grn'   => $grn,
            'items' => $items,
        ]);
    }

    public function inspect(Request $request, string $id): Response
    {
        $grnItemIds       = $request->post('grn_item_ids', []);
        $quantitiesAcc    = $request->post('quantities_accepted', []);
        $quantitiesRej    = $request->post('quantities_rejected', []);
        $rejectionReasons = $request->post('rejection_reasons', []);
        $inspectionNotes  = trim((string) $request->post('inspection_notes', '')) ?: null;

        if (!is_array($grnItemIds) || empty($grnItemIds)) {
            return $this->redirect('/procurement/grn/' . $id . '/inspect')->withError('لا توجد أصناف للفحص');
        }

        $inspectedItems = [];
        foreach ($grnItemIds as $i => $grnItemId) {
            $inspectedItems[] = [
                'grn_item_id'      => (int) $grnItemId,
                'quantity_accepted' => (string) ($quantitiesAcc[$i] ?? '0'),
                'quantity_rejected' => (string) ($quantitiesRej[$i] ?? '0'),
                'rejection_reason'  => $rejectionReasons[$i] ?? null,
            ];
        }

        try {
            GoodsReceivingService::inspectGRN((int) $id, $inspectedItems, $inspectionNotes);
            return $this->redirect('/procurement/grn/' . $id)->withSuccess('تم فحص واعتماد إذن الاستلام بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/grn/' . $id . '/inspect')->withError($e->getMessage());
        }
    }

    public function cancel(Request $request, string $id): Response
    {
        try {
            GoodsReceivingService::cancelGRN((int) $id);
            return $this->redirect('/procurement/grn/' . $id)->withSuccess('تم إلغاء إذن الاستلام');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/grn/' . $id)->withError($e->getMessage());
        }
    }
}
