<?php

declare(strict_types=1);

namespace App\Models;

class Product extends BaseModel
{
    protected string $table = 'productos';

    public function listByCompany(int $companyId): array
    {
        $stmt = $this->db()->prepare(
            'SELECT
                p.id,
                p.empresa_id,
                p.categoria_id,
                p.proveedor_id,
                p.unidad_medida_id,
                p.nombre,
                p.sku,
                p.codigo_barras,
                p.precio_compra,
                p.precio_venta,
                p.impuesto_porcentaje,
                p.stock_actual,
                p.stock_minimo,
                p.imagen,
                p.activo,
                c.nombre AS categoria,
                s.nombre AS proveedor_nombre,
                um.nombre AS unidad_nombre,
                um.abreviatura AS unidad_abreviatura
             FROM productos p
             LEFT JOIN categorias c ON c.id = p.categoria_id
             LEFT JOIN proveedores s ON s.id = p.proveedor_id
             LEFT JOIN unidades_medida um ON um.id = p.unidad_medida_id
             WHERE p.empresa_id = :empresa_id
             ORDER BY p.id DESC'
        );
        $stmt->execute([':empresa_id' => $companyId]);

        return $stmt->fetchAll() ?: [];
    }

    public function listForPos(int $companyId, ?int $branchId = null): array
    {
        if ($branchId === null || $branchId <= 0) {
            $sql = 'SELECT
                        p.id,
                        p.nombre,
                        p.sku,
                        p.codigo_barras,
                        p.imagen,
                        p.precio_venta,
                        p.impuesto_porcentaje,
                        p.stock_actual,
                        c.nombre AS categoria
                    FROM productos p
                    LEFT JOIN categorias c ON c.id = p.categoria_id
                    WHERE p.empresa_id = :empresa_id
                      AND p.activo = 1
                    ORDER BY p.nombre ASC';

            $stmt = $this->db()->prepare($sql);
            $stmt->execute([':empresa_id' => $companyId]);

            return $stmt->fetchAll() ?: [];
        }

        $stmt = $this->db()->prepare(
            'SELECT
                p.id,
                p.nombre,
                p.sku,
                p.codigo_barras,
                p.imagen,
                p.precio_venta,
                p.impuesto_porcentaje,
                p.stock_actual AS stock_global,
                p.sucursal_id,
                c.nombre AS categoria,
                ib.stock AS stock_sucursal,
                (
                    SELECT COUNT(*)
                    FROM inventario ix
                    WHERE ix.empresa_id = p.empresa_id
                      AND ix.producto_id = p.id
                      AND ix.sucursal_id IS NOT NULL
                ) AS total_stock_sucursales
             FROM productos p
             LEFT JOIN categorias c ON c.id = p.categoria_id
             LEFT JOIN inventario ib
                ON ib.empresa_id = p.empresa_id
               AND ib.producto_id = p.id
               AND ib.sucursal_id = :inv_sucursal_id
             WHERE p.empresa_id = :empresa_id
               AND p.activo = 1
             ORDER BY p.nombre ASC'
        );
        $stmt->execute([
            ':inv_sucursal_id' => $branchId,
            ':empresa_id' => $companyId,
        ]);

        $rows = $stmt->fetchAll() ?: [];
        $products = [];

        foreach ($rows as $row) {
            $stockByBranch = $row['stock_sucursal'] !== null ? (float) $row['stock_sucursal'] : null;
            $totalBranchRows = (int) ($row['total_stock_sucursales'] ?? 0);
            $productBranchId = $row['sucursal_id'] !== null ? (int) $row['sucursal_id'] : null;
            $stock = 0.0;

            if ($stockByBranch !== null) {
                $stock = $stockByBranch;
            } elseif ($totalBranchRows === 0 && ($productBranchId === null || $productBranchId === $branchId)) {
                $stock = (float) ($row['stock_global'] ?? 0);
            }

            if ($stock <= 0) {
                continue;
            }

            $row['stock_actual'] = $stock;
            $products[] = $row;
        }

        return $products;
    }

    public function adjustStock(int $productId, int $companyId, float $quantity): void
    {
        $sql = 'UPDATE productos
                SET stock_actual = stock_actual + :cantidad
                WHERE id = :id AND empresa_id = :empresa_id';
        $stmt = $this->db()->prepare($sql);
        $stmt->execute([
            ':cantidad' => $quantity,
            ':id' => $productId,
            ':empresa_id' => $companyId,
        ]);
    }

    public function findBySku(int $companyId, string $sku): ?array
    {
        $normalizedSku = trim($sku);
        if ($normalizedSku === '') {
            return null;
        }

        $stmt = $this->db()->prepare(
            'SELECT * FROM productos
             WHERE empresa_id = :empresa_id
               AND sku IS NOT NULL
               AND LOWER(TRIM(sku)) = LOWER(:sku)
             LIMIT 1'
        );
        $stmt->execute([':empresa_id' => $companyId, ':sku' => $normalizedSku]);
        $result = $stmt->fetch();

        return $result ?: null;
    }

    public function skuExists(int $companyId, string $sku, ?int $excludeProductId = null): bool
    {
        $normalizedSku = trim($sku);
        if ($normalizedSku === '') {
            return false;
        }

        $sql = 'SELECT id
                FROM productos
                WHERE empresa_id = :empresa_id
                  AND sku IS NOT NULL
                  AND TRIM(sku) <> ""
                  AND LOWER(TRIM(sku)) = LOWER(:sku)';

        $params = [
            ':empresa_id' => $companyId,
            ':sku' => $normalizedSku,
        ];

        if ($excludeProductId !== null && $excludeProductId > 0) {
            $sql .= ' AND id <> :exclude_id';
            $params[':exclude_id'] = $excludeProductId;
        }

        $sql .= ' LIMIT 1';

        $stmt = $this->db()->prepare($sql);
        $stmt->execute($params);

        return (bool) $stmt->fetch();
    }
}
