<?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\PurchaseRequisition;
use App\Modules\Procurement\Models\PurchaseRequisitionItem;
use App\Modules\Procurement\Services\RequisitionService;
use App\Modules\Inventory\Models\InventoryItem;
use App\Modules\Inventory\Models\Supplier;
use App\Modules\Inventory\Models\Warehouse;

class RequisitionController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'status'       => trim((string) $request->get('status', '')),
            'urgency'      => trim((string) $request->get('urgency', '')),
            'requested_by' => trim((string) $request->get('requested_by', '')),
            '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 = PurchaseRequisition::search($filters, 25, $page);

        return $this->view('Procurement.Views.requisitions.index', [
            'requisitions' => $result['data'],
            'pagination'   => $result['pagination'],
            'filters'      => $filters,
            'statuses'     => PurchaseRequisition::getStatuses(),
            'urgencies'    => PurchaseRequisition::getUrgencyLevels(),
        ]);
    }

    public function create(Request $request): Response
    {
        return $this->view('Procurement.Views.requisitions.form', [
            'items'     => InventoryItem::allActive(),
            'suppliers' => Supplier::allActive(),
            'urgencies' => PurchaseRequisition::getUrgencyLevels(),
        ]);
    }

    public function store(Request $request): Response
    {
        $header = [
            'department'    => trim((string) $request->post('department', '')) ?: null,
            'urgency'       => trim((string) $request->post('urgency', 'normal')),
            'required_date' => trim((string) $request->post('required_date', '')) ?: null,
            'justification' => trim((string) $request->post('justification', '')) ?: null,
            'notes'         => trim((string) $request->post('notes', '')) ?: null,
        ];

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

        $items = [];
        foreach ($rawItems as $raw) {
            $qty = (string) ($raw['quantity'] ?? '0');
            if (bccomp($qty, '0', 3) > 0) {
                $items[] = [
                    'item_id'               => !empty($raw['item_id']) ? (int) $raw['item_id'] : null,
                    'description_ar'        => $raw['description_ar'] ?? null,
                    'quantity'              => $qty,
                    'unit_of_measure'       => $raw['unit_of_measure'] ?? null,
                    'estimated_unit_cost'   => $raw['estimated_unit_cost'] ?? null,
                    'specifications'        => $raw['specifications'] ?? null,
                    'preferred_supplier_id' => !empty($raw['preferred_supplier_id']) ? (int) $raw['preferred_supplier_id'] : null,
                ];
            }
        }

        try {
            $prId = RequisitionService::createPR($header, $items);
            return $this->redirect('/procurement/requisitions/' . $prId)->withSuccess('تم إنشاء طلب الشراء بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/requisitions/create')->withError($e->getMessage());
        }
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $pr = $db->selectOne(
            "SELECT pr.*, e.`full_name_ar` as requester_name,
                    ea.`full_name_ar` as approver_name,
                    er.`full_name_ar` as rejector_name
             FROM `purchase_requisitions` pr
             LEFT JOIN `employees` e ON e.`id` = pr.`requested_by`
             LEFT JOIN `employees` ea ON ea.`id` = pr.`approved_by`
             LEFT JOIN `employees` er ON er.`id` = pr.`rejected_by`
             WHERE pr.`id` = ?",
            [(int) $id]
        );

        if (!$pr) {
            return $this->redirect('/procurement/requisitions')->withError('طلب الشراء غير موجود');
        }

        $items = PurchaseRequisitionItem::getForRequisition((int) $id);

        return $this->view('Procurement.Views.requisitions.show', [
            'pr'       => $pr,
            'items'    => $items,
            'statuses' => PurchaseRequisition::getStatuses(),
        ]);
    }

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

        if (!$pr) {
            return $this->redirect('/procurement/requisitions')->withError('طلب الشراء غير موجود');
        }
        if ($pr['status'] !== 'draft') {
            return $this->redirect('/procurement/requisitions/' . $id)->withError('لا يمكن تعديل طلب الشراء إلا في حالة المسودة');
        }

        $prItems = PurchaseRequisitionItem::getForRequisition((int) $id);

        return $this->view('Procurement.Views.requisitions.form', [
            'pr'        => $pr,
            'prItems'   => $prItems,
            'items'     => InventoryItem::allActive(),
            'suppliers' => Supplier::allActive(),
            'urgencies' => PurchaseRequisition::getUrgencyLevels(),
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $header = [
            'department'    => trim((string) $request->post('department', '')) ?: null,
            'urgency'       => trim((string) $request->post('urgency', 'normal')),
            'required_date' => trim((string) $request->post('required_date', '')) ?: null,
            'justification' => trim((string) $request->post('justification', '')) ?: null,
            'notes'         => trim((string) $request->post('notes', '')) ?: null,
        ];

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

        $items = [];
        foreach ($rawItems as $raw) {
            $qty = (string) ($raw['quantity'] ?? '0');
            if (bccomp($qty, '0', 3) > 0) {
                $items[] = [
                    'item_id'               => !empty($raw['item_id']) ? (int) $raw['item_id'] : null,
                    'description_ar'        => $raw['description_ar'] ?? null,
                    'quantity'              => $qty,
                    'unit_of_measure'       => $raw['unit_of_measure'] ?? null,
                    'estimated_unit_cost'   => $raw['estimated_unit_cost'] ?? null,
                    'specifications'        => $raw['specifications'] ?? null,
                    'preferred_supplier_id' => !empty($raw['preferred_supplier_id']) ? (int) $raw['preferred_supplier_id'] : null,
                ];
            }
        }

        try {
            RequisitionService::updatePR((int) $id, $header, $items);
            return $this->redirect('/procurement/requisitions/' . $id)->withSuccess('تم تحديث طلب الشراء بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/requisitions/' . $id . '/edit')->withError($e->getMessage());
        }
    }

    public function submit(Request $request, string $id): Response
    {
        try {
            RequisitionService::submitPR((int) $id);
            return $this->redirect('/procurement/requisitions/' . $id)->withSuccess('تم تقديم طلب الشراء للاعتماد');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/requisitions/' . $id)->withError($e->getMessage());
        }
    }

    public function approve(Request $request, string $id): Response
    {
        try {
            RequisitionService::approvePR((int) $id);
            return $this->redirect('/procurement/requisitions/' . $id)->withSuccess('تم اعتماد طلب الشراء');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/requisitions/' . $id)->withError($e->getMessage());
        }
    }

    public function reject(Request $request, string $id): Response
    {
        $reason = trim((string) $request->post('rejection_reason', ''));
        if (empty($reason)) {
            return $this->redirect('/procurement/requisitions/' . $id)->withError('يجب إدخال سبب الرفض');
        }

        try {
            RequisitionService::rejectPR((int) $id, $reason);
            return $this->redirect('/procurement/requisitions/' . $id)->withSuccess('تم رفض طلب الشراء');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/requisitions/' . $id)->withError($e->getMessage());
        }
    }

    public function convert(Request $request, string $id): Response
    {
        $poHeader = [
            '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,
        ];

        try {
            $poId = RequisitionService::convertToPO((int) $id, $poHeader);
            return $this->redirect('/inventory/purchase-orders/' . $poId)->withSuccess('تم تحويل طلب الشراء إلى أمر شراء بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/requisitions/' . $id)->withError($e->getMessage());
        }
    }

    public function cancel(Request $request, string $id): Response
    {
        try {
            RequisitionService::cancelPR((int) $id);
            return $this->redirect('/procurement/requisitions/' . $id)->withSuccess('تم إلغاء طلب الشراء');
        } catch (\RuntimeException $e) {
            return $this->redirect('/procurement/requisitions/' . $id)->withError($e->getMessage());
        }
    }
}
