<?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\StockAudit;
use App\Modules\Inventory\Models\StockAuditItem;
use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Models\ItemCategory;
use App\Modules\Inventory\Services\StockAuditService;

class StockAuditController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'status'       => trim((string) $request->get('status', '')),
            'audit_type'   => trim((string) $request->get('audit_type', '')),
            'warehouse_id' => trim((string) $request->get('warehouse_id', '')),
        ];

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

        return $this->view('Inventory.Views.audits.index', [
            'audits'     => $result['data'],
            'pagination' => $result['pagination'],
            'filters'    => $filters,
            'statuses'   => StockAudit::getStatuses(),
            'auditTypes' => StockAudit::getAuditTypes(),
            'warehouses' => Warehouse::allActive(),
        ]);
    }

    public function create(Request $request): Response
    {
        return $this->view('Inventory.Views.audits.form', [
            'auditTypes' => StockAudit::getAuditTypes(),
            'warehouses' => Warehouse::allActive(),
            'categories' => ItemCategory::allActive(),
        ]);
    }

    public function store(Request $request): Response
    {
        $warehouseId = (int) $request->post('warehouse_id', 0);
        $auditType   = trim((string) $request->post('audit_type', ''));
        $categoryId  = ((int) $request->post('category_id', 0)) ?: null;
        $notes       = trim((string) $request->post('notes', ''));

        $errors = [];
        if ($warehouseId <= 0) $errors[] = 'يجب اختيار المخزن';
        if (!array_key_exists($auditType, StockAudit::getAuditTypes())) $errors[] = 'نوع الجرد غير صالح';

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/inventory/audits/create');
        }

        try {
            $auditId = StockAuditService::createAudit($warehouseId, $auditType, $categoryId, $notes ?: null);
            return $this->redirect('/inventory/audits/' . $auditId . '/count')->withSuccess('تم إنشاء الجرد — يمكنك البدء في العد');
        } catch (\RuntimeException $e) {
            return $this->redirect('/inventory/audits/create')->withError($e->getMessage());
        }
    }

    public function show(Request $request, string $id): Response
    {
        $audit = StockAudit::find((int) $id);
        if (!$audit) {
            return $this->redirect('/inventory/audits')->withError('الجرد غير موجود');
        }

        $items = StockAuditItem::getForAudit((int) $id);

        $db = App::getInstance()->db();
        $warehouse = $db->selectOne("SELECT `name_ar`, `code` FROM `warehouses` WHERE `id` = ?", [(int) $audit->warehouse_id]);

        return $this->view('Inventory.Views.audits.show', [
            'audit'     => $audit,
            'items'     => $items,
            'warehouse' => $warehouse,
        ]);
    }

    public function count(Request $request, string $id): Response
    {
        $audit = StockAudit::find((int) $id);
        if (!$audit) {
            return $this->redirect('/inventory/audits')->withError('الجرد غير موجود');
        }

        if (!in_array($audit->status, ['in_progress', 'draft'], true)) {
            return $this->redirect('/inventory/audits/' . $id)->withError('لا يمكن إدخال العد في هذه الحالة');
        }

        $items = StockAuditItem::getForAudit((int) $id);

        return $this->view('Inventory.Views.audits.count', [
            'audit' => $audit,
            'items' => $items,
        ]);
    }

    public function saveCount(Request $request, string $id): Response
    {
        $audit = StockAudit::find((int) $id);
        if (!$audit) {
            return $this->redirect('/inventory/audits')->withError('الجرد غير موجود');
        }

        $physicalQtys = $request->post('physical_quantities', []);

        $counts = [];
        foreach ($physicalQtys as $auditItemId => $qty) {
            if ($qty !== '' && $qty !== null) {
                $counts[(int) $auditItemId] = (string) $qty;
            }
        }

        if (empty($counts)) {
            return $this->redirect('/inventory/audits/' . $id . '/count')->withError('يجب إدخال كمية واحدة على الأقل');
        }

        StockAuditService::saveCounts((int) $id, $counts);

        return $this->redirect('/inventory/audits/' . $id)->withSuccess('تم حفظ العد — في انتظار الاعتماد');
    }

    public function approve(Request $request, string $id): Response
    {
        try {
            StockAuditService::approveAudit((int) $id);
            return $this->redirect('/inventory/audits/' . $id)->withSuccess('تم اعتماد الجرد وتنفيذ التسويات');
        } catch (\RuntimeException $e) {
            return $this->redirect('/inventory/audits/' . $id)->withError($e->getMessage());
        }
    }
}
