<?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\InventoryItem;
use App\Modules\Inventory\Models\ItemCategory;
use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Models\ItemWarehouseStock;
use App\Modules\Inventory\Services\StockService;

class ItemController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'q'             => trim((string) $request->get('q', '')),
            'category_id'   => trim((string) $request->get('category_id', '')),
            'tracking_type' => trim((string) $request->get('tracking_type', '')),
            'is_sellable'   => $request->get('is_sellable', ''),
            'warehouse_id'  => trim((string) $request->get('warehouse_id', '')),
        ];

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

        return $this->view('Inventory.Views.items.index', [
            'items'         => $result['data'],
            'pagination'    => $result['pagination'],
            'filters'       => $filters,
            'categories'    => ItemCategory::allActive(),
            'trackingTypes' => InventoryItem::getTrackingTypes(),
            'warehouses'    => Warehouse::allActive(),
        ]);
    }

    public function create(Request $request): Response
    {
        return $this->view('Inventory.Views.items.form', [
            'item'          => null,
            'categories'    => ItemCategory::allActive(),
            'trackingTypes' => InventoryItem::getTrackingTypes(),
            'units'         => InventoryItem::getUnitsOfMeasure(),
        ]);
    }

    public function store(Request $request): Response
    {
        $data = $this->extractData($request);
        $errors = $this->validateInput($data);

        // Unique SKU
        if ($data['sku'] !== '') {
            $existing = InventoryItem::query()->where('sku', '=', $data['sku'])->first();
            if ($existing) {
                $errors[] = 'كود الصنف (SKU) مستخدم بالفعل';
            }
        }

        if (!empty($errors)) {
            return $this->flashErrorsAndRedirect($errors, $request, '/inventory/items/create');
        }

        $item = InventoryItem::create($data);

        return $this->redirect('/inventory/items/' . $item->id)->withSuccess('تم إضافة الصنف بنجاح');
    }

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

        $db = App::getInstance()->db();

        // Category name
        $category = $item->category_id ? ItemCategory::find((int) $item->category_id) : null;

        // Stock per warehouse
        $stockRecords = $db->select(
            "SELECT iws.*, w.`name_ar` as warehouse_name, w.`code` as warehouse_code
             FROM `item_warehouse_stock` iws
             JOIN `warehouses` w ON w.`id` = iws.`warehouse_id`
             WHERE iws.`item_id` = ?
             ORDER BY w.`name_ar` ASC",
            [(int) $id]
        );

        $totalStock = InventoryItem::getTotalStock((int) $id);

        // Recent movements
        $movements = StockService::getMovements((int) $id, null, 20);

        return $this->view('Inventory.Views.items.show', [
            'item'          => $item,
            'category'      => $category,
            'stockRecords'  => $stockRecords,
            'totalStock'    => $totalStock,
            'movements'     => $movements,
            'trackingTypes' => InventoryItem::getTrackingTypes(),
            'units'         => InventoryItem::getUnitsOfMeasure(),
        ]);
    }

    public function edit(Request $request, string $id): Response
    {
        $item = InventoryItem::find((int) $id);
        if (!$item) {
            return $this->redirect('/inventory/items')->withError('الصنف غير موجود');
        }

        return $this->view('Inventory.Views.items.form', [
            'item'          => $item,
            'categories'    => ItemCategory::allActive(),
            'trackingTypes' => InventoryItem::getTrackingTypes(),
            'units'         => InventoryItem::getUnitsOfMeasure(),
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $item = InventoryItem::find((int) $id);
        if (!$item) {
            return $this->redirect('/inventory/items')->withError('الصنف غير موجود');
        }

        $data = $this->extractData($request);
        $errors = $this->validateInput($data);

        // Unique SKU (exclude current)
        if ($data['sku'] !== '') {
            $existing = InventoryItem::query()
                ->where('sku', '=', $data['sku'])
                ->whereRaw('`id` != ?', [(int) $id])
                ->first();
            if ($existing) {
                $errors[] = 'كود الصنف (SKU) مستخدم بالفعل';
            }
        }

        if (!empty($errors)) {
            return $this->flashErrorsAndRedirect($errors, $request, '/inventory/items/' . $id . '/edit');
        }

        $item->update($data);

        return $this->redirect('/inventory/items/' . $id)->withSuccess('تم تحديث الصنف بنجاح');
    }

    /**
     * JSON search endpoint for AJAX item lookup (POS, transfers, etc.)
     */
    public function searchJson(Request $request): Response
    {
        $q = trim((string) $request->get('q', ''));
        if (mb_strlen($q) < 2) {
            return $this->json(['results' => []]);
        }

        $db = App::getInstance()->db();
        $search = '%' . $q . '%';
        $rows = $db->select(
            "SELECT `id`, `sku`, `name_ar`, `sale_price_member`, `sale_price_nonmember`, `unit_of_measure`, `tracking_type`
             FROM `inventory_items`
             WHERE (`name_ar` LIKE ? OR `sku` LIKE ? OR `barcode` LIKE ?)
               AND `is_active` = 1 AND `is_archived` = 0
             ORDER BY `name_ar` ASC LIMIT 20",
            [$search, $search, $search]
        );

        return $this->json(['results' => $rows]);
    }

    private function extractData(Request $request): array
    {
        return [
            'category_id'          => ((int) $request->post('category_id', 0)) ?: null,
            'sku'                  => strtoupper(trim((string) $request->post('sku', ''))),
            'barcode'              => trim((string) $request->post('barcode', '')) ?: null,
            'name_ar'              => trim((string) $request->post('name_ar', '')),
            'name_en'              => trim((string) $request->post('name_en', '')) ?: null,
            'description_ar'       => trim((string) $request->post('description_ar', '')) ?: null,
            'unit_of_measure'      => trim((string) $request->post('unit_of_measure', 'piece')),
            'tracking_type'        => trim((string) $request->post('tracking_type', 'standard')),
            'cost_price'           => trim((string) $request->post('cost_price', '0.00')),
            'sale_price_member'    => trim((string) $request->post('sale_price_member', '0.00')),
            'sale_price_nonmember' => trim((string) $request->post('sale_price_nonmember', '0.00')),
            'sale_price_player'    => trim((string) $request->post('sale_price_player', '')) ?: null,
            'tax_rate'             => trim((string) $request->post('tax_rate', '14.00')),
            'is_sellable'          => (int) ($request->post('is_sellable', 1)),
            'is_active'            => (int) ($request->post('is_active', 1)),
            'notes'                => trim((string) $request->post('notes', '')) ?: null,
        ];
    }

    private function validateInput(array $data): array
    {
        $errors = [];
        if ($data['sku'] === '') {
            $errors[] = 'كود الصنف (SKU) مطلوب';
        }
        if ($data['name_ar'] === '' || mb_strlen($data['name_ar']) < 2) {
            $errors[] = 'اسم الصنف بالعربي مطلوب (حرفان على الأقل)';
        }
        if (!array_key_exists($data['tracking_type'], InventoryItem::getTrackingTypes())) {
            $errors[] = 'نوع التتبع غير صالح';
        }
        if (!array_key_exists($data['unit_of_measure'], InventoryItem::getUnitsOfMeasure())) {
            $errors[] = 'وحدة القياس غير صالحة';
        }
        return $errors;
    }

    private function flashErrorsAndRedirect(array $errors, Request $request, string $url): Response
    {
        $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($url);
    }
}
