<?php

declare(strict_types=1);

namespace App\Models;

class PurchaseOrder extends BaseModel
{
    protected string $table = 'ordenes_compra';
    /** @var array<string,bool> */
    private array $columnAvailabilityCache = [];

    public function listWithProgress(int $companyId, int $limit = 60): array
    {
        $limit = max(1, min(150, $limit));

        $sql = 'SELECT
                    oc.id,
                    oc.numero,
                    oc.fecha,
                    oc.subtotal,
                    oc.impuestos,
                    oc.total,
                    oc.estado,
                    oc.observacion,
                    oc.created_at,
                    p.nombre AS proveedor,
                    u.nombre AS usuario,
                    s.nombre AS sucursal,
                    COALESCE(SUM(od.cantidad), 0) AS cantidad_ordenada,
                    COALESCE(SUM(od.cantidad_recibida), 0) AS cantidad_recibida
                FROM ordenes_compra oc
                INNER JOIN proveedores p ON p.id = oc.proveedor_id
                INNER JOIN usuarios u ON u.id = oc.usuario_id
                LEFT JOIN sucursales s ON s.id = oc.sucursal_id
                LEFT JOIN orden_compra_detalles od ON od.orden_compra_id = oc.id
                WHERE oc.empresa_id = :empresa_id
                GROUP BY
                    oc.id, oc.numero, oc.fecha, oc.subtotal, oc.impuestos, oc.total, oc.estado,
                    oc.observacion, oc.created_at, p.nombre, u.nombre, s.nombre
                ORDER BY oc.id DESC
                LIMIT :limit';

        $stmt = $this->db()->prepare($sql);
        $stmt->bindValue(':empresa_id', $companyId, \PDO::PARAM_INT);
        $stmt->bindValue(':limit', $limit, \PDO::PARAM_INT);
        $stmt->execute();

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

    public function detailsByOrder(int $companyId, int $orderId): array
    {
        $hasVariantColumn = $this->tableHasColumn('orden_compra_detalles', 'variante_id');
        $variantSelect = $hasVariantColumn ? 'od.variante_id, v.nombre AS variante_nombre,' : 'NULL AS variante_id, NULL AS variante_nombre,';
        $variantJoin = $hasVariantColumn
            ? ' LEFT JOIN producto_variantes v ON v.id = od.variante_id AND v.empresa_id = od.empresa_id '
            : '';

        $sql = 'SELECT
                    od.id,
                    od.orden_compra_id,
                    od.producto_id,
                    ' . $variantSelect . '
                    od.cantidad,
                    od.cantidad_recibida,
                    (od.cantidad - od.cantidad_recibida) AS cantidad_pendiente,
                    od.costo_unitario,
                    od.impuesto,
                    od.total_linea,
                    p.nombre AS producto
                FROM orden_compra_detalles od
                INNER JOIN ordenes_compra oc ON oc.id = od.orden_compra_id AND oc.empresa_id = od.empresa_id
                INNER JOIN productos p ON p.id = od.producto_id AND p.empresa_id = od.empresa_id'
                . $variantJoin .
                'WHERE od.empresa_id = :empresa_id
                  AND od.orden_compra_id = :orden_id
                ORDER BY od.id ASC';

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

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

    public function receptionHistoryByOrder(int $companyId, int $orderId): array
    {
        $sql = 'SELECT
                    rc.id,
                    rc.numero_recepcion,
                    rc.fecha_recepcion,
                    rc.estado,
                    rc.observacion,
                    COALESCE(SUM(rcd.total_linea), 0) AS total_recepcion
                FROM recepciones_compra rc
                LEFT JOIN recepcion_compra_detalles rcd ON rcd.recepcion_id = rc.id AND rcd.empresa_id = rc.empresa_id
                WHERE rc.empresa_id = :empresa_id
                  AND rc.orden_compra_id = :orden_id
                GROUP BY rc.id, rc.numero_recepcion, rc.fecha_recepcion, rc.estado, rc.observacion
                ORDER BY rc.id DESC';

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

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

    private function tableHasColumn(string $table, string $column): bool
    {
        $cacheKey = $table . '.' . $column;
        if (array_key_exists($cacheKey, $this->columnAvailabilityCache)) {
            return $this->columnAvailabilityCache[$cacheKey];
        }

        $stmt = $this->db()->prepare(
            "SELECT COUNT(*) FROM information_schema.COLUMNS
             WHERE TABLE_SCHEMA = DATABASE()
               AND TABLE_NAME = :table
               AND COLUMN_NAME = :column"
        );
        $stmt->execute([
            ':table' => $table,
            ':column' => $column,
        ]);

        $this->columnAvailabilityCache[$cacheKey] = (int) $stmt->fetchColumn() > 0;
        return $this->columnAvailabilityCache[$cacheKey];
    }
}
