<?php

namespace Core\App\Controllers;

use Core\App\Models\ProductModel;

class InventoryController
{
    private ProductModel $products;

    public function __construct()
    {
        $this->products = new ProductModel();
        $this->requireAuth();
    }

    /* =====================================================
     * CSRF Check (for AJAX endpoints)
     * ===================================================== */
    private function checkCsrf(): bool
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        // Accept token from POST body OR X-CSRF-TOKEN header
        $token = $_POST['_csrf'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
        return $token !== ''
            && !empty($_SESSION['_csrf'])
            && hash_equals((string)$_SESSION['_csrf'], trim($token));
    }

    /* =====================================================
     * Auth Guard
     * ===================================================== */
    private function requireAuth(): void
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }

        if (empty($_SESSION['admin_id'])) {
            header('Location: /admin/login');
            exit;
        }
    }

    /* =====================================================
     * Main Inventory Page
     * ===================================================== */
    public function index(): void
    {
        // Fetch all products with full data
        $allProducts = $this->products->getAll();

        // Build enriched inventory rows
        $rows = [];
        foreach ($allProducts as $product) {
            $productId   = (int)$product['id'];
            $variants    = is_array($product['variants']) ? $product['variants'] : [];
            $hasVariants = !empty($variants['sizes']) || !empty($variants['colors']);

            // Variant stock from product_variant_stock table
            $variantStock = [];
            if ($hasVariants) {
                $rawStock = $this->products->getAllVariantStock($productId);

                // Build valid combinations from current variants definition (exclude ghost/stale rows)
                $sizesVals  = array_column($variants['sizes']  ?? [], 'value');
                $colorsVals = array_column($variants['colors'] ?? [], 'name');
                $validCombos = [];
                if (!empty($sizesVals) && !empty($colorsVals)) {
                    foreach ($sizesVals as $sz) {
                        foreach ($colorsVals as $cl) {
                            $validCombos[] = ['size' => $sz, 'color' => $cl];
                        }
                    }
                } elseif (!empty($sizesVals)) {
                    foreach ($sizesVals as $sz) {
                        $validCombos[] = ['size' => $sz, 'color' => null];
                    }
                } elseif (!empty($colorsVals)) {
                    foreach ($colorsVals as $cl) {
                        $validCombos[] = ['size' => null, 'color' => $cl];
                    }
                }

                // Filter raw stock to only valid combinations
                $variantStock = array_values(array_filter($rawStock, function ($vs) use ($validCombos) {
                    $vSize  = $vs['size']  ?? null;
                    $vColor = $vs['color'] ?? null;
                    // Normalise empty strings to null for comparison
                    if ($vSize  === '') $vSize  = null;
                    if ($vColor === '') $vColor = null;
                    foreach ($validCombos as $combo) {
                        if ($vSize === $combo['size'] && $vColor === $combo['color']) {
                            return true;
                        }
                    }
                    return false;
                }));
            }

            // Resolve effective stock: if variants exist, sum variant stock; else use stock_quantity
            $totalStock = (int)$product['stock_quantity'];
            if ($hasVariants && !empty($variantStock)) {
                $totalStock = (int)array_sum(array_column($variantStock, 'quantity'));
            }

            $alertThreshold = (int)($product['stock_alert'] ?? 5);

            // Determine stock status
            if ($totalStock === 0) {
                $stockStatus = 'out';
            } elseif ($totalStock <= $alertThreshold) {
                $stockStatus = 'low';
            } else {
                $stockStatus = 'ok';
            }

            // Effective price for value calculation
            $price = (float)($product['sale_price'] ?: $product['price'] ?? 0);

            $rows[] = [
                'id'              => $productId,
                'title'           => $product['title'],
                'slug'            => $product['slug'] ?? '',
                'sku'             => $product['sku'] ?? '',
                'barcode'         => $product['barcode'] ?? '',
                'featured_image'  => $product['featured_image'] ?? '',
                'price'           => (float)($product['price'] ?? 0),
                'sale_price'      => (float)($product['sale_price'] ?? 0),
                'effective_price' => $price,
                'status'          => $product['status'] ?? 'active',
                'stock_quantity'  => $totalStock,
                'stock_alert'     => $alertThreshold,
                'stock_status'    => $stockStatus,
                'has_variants'    => $hasVariants,
                'variant_stock'   => $variantStock,
                'variants_def'    => $variants,
                'stock_value'     => round($price * $totalStock, 2),
                'updated_at'      => $product['updated_at'] ?? $product['created_at'] ?? '',
                'created_at'      => $product['created_at'] ?? '',
            ];
        }

        // KPI stats
        $totalProducts  = count($rows);
        $totalUnits     = (int)array_sum(array_column($rows, 'stock_quantity'));
        $outOfStock     = count(array_filter($rows, fn($r) => $r['stock_status'] === 'out'));
        $lowStock       = count(array_filter($rows, fn($r) => $r['stock_status'] === 'low'));
        $totalValue     = round(array_sum(array_column($rows, 'stock_value')), 2);
        $activeProducts = count(array_filter($rows, fn($r) => $r['status'] === 'active'));

        // Sort: out of stock first, then low stock, then ok — within each group by title
        usort($rows, function ($a, $b) {
            $order = ['out' => 0, 'low' => 1, 'ok' => 2];
            $diff  = ($order[$a['stock_status']] ?? 9) - ($order[$b['stock_status']] ?? 9);
            if ($diff !== 0) return $diff;
            return strcmp($a['title'], $b['title']);
        });

        require __DIR__ . '/../../../admin/templates/inventory/index.php';
    }

    /* =====================================================
     * AJAX: Update Product Stock (non-variant)
     * POST /admin/inventory/update-stock/{id}
     * ===================================================== */
    public function updateStock(int $id): void
    {
        header('Content-Type: application/json; charset=utf-8');

        if (!$this->checkCsrf()) {
            http_response_code(403);
            echo json_encode(['success' => false, 'error' => 'invalid_csrf']);
            return;
        }

        $qty = isset($_POST['quantity']) ? (int)$_POST['quantity'] : null;

        if ($qty === null || $qty < 0) {
            http_response_code(422);
            echo json_encode(['success' => false, 'error' => 'invalid_quantity']);
            return;
        }

        $this->products->setStock($id, $qty);

        echo json_encode(['success' => true, 'quantity' => $qty]);
    }

    /* =====================================================
     * AJAX: Update Variant Stock
     * POST /admin/inventory/update-variant-stock/{id}
     * ===================================================== */
    public function updateVariantStock(int $id): void
    {
        header('Content-Type: application/json; charset=utf-8');

        if (!$this->checkCsrf()) {
            http_response_code(403);
            echo json_encode(['success' => false, 'error' => 'invalid_csrf']);
            return;
        }

        $size  = isset($_POST['size'])  ? trim($_POST['size'])  : null;
        $color = isset($_POST['color']) ? trim($_POST['color']) : null;
        $qty   = isset($_POST['quantity']) ? (int)$_POST['quantity'] : null;

        if ($qty === null || $qty < 0) {
            http_response_code(422);
            echo json_encode(['success' => false, 'error' => 'invalid_quantity']);
            return;
        }

        if ($size  === '') $size  = null;
        if ($color === '') $color = null;

        $this->products->setVariantStock($id, $size, $color, $qty);

        echo json_encode(['success' => true, 'quantity' => $qty]);
    }
}
