<?php
/**
 * Model Produto (completo)
 * Localização: /app/models/Produto.php
 *
 * v1.1 — corrigido bug HY093 em relacionados() (parâmetro :cat duplicado)
 */
require_once APP_PATH . '/core/Model.php';

class Produto extends Model
{
    protected string $table = 'produtos';

    /**
     * Busca produtos do catálogo público com filtros
     */
    public function filtrar(array $f = [], int $page = 1, int $perPage = 12): array
    {
        $where = ["p.ativo = 1"];
        $params = [];

        if (!empty($f['categoria'])) {
            $where[] = "c.slug = :cat";
            $params[':cat'] = $f['categoria'];
        }
        if (!empty($f['colecao'])) {
            $where[] = "co.slug = :col";
            $params[':col'] = $f['colecao'];
        }
        if (!empty($f['material'])) {
            $where[] = "p.material_armacao LIKE :mat";
            $params[':mat'] = '%' . $f['material'] . '%';
        }
        if (!empty($f['polarizado'])) {
            $where[] = "p.polarizado = 1";
        }
        if (!empty($f['uv'])) {
            $where[] = "p.protecao_uv IS NOT NULL AND p.protecao_uv <> ''";
        }
        if (!empty($f['cor'])) {
            $where[] = "EXISTS (SELECT 1 FROM produto_variacoes v WHERE v.produto_id = p.id AND v.cor LIKE :cor)";
            $params[':cor'] = '%' . $f['cor'] . '%';
        }
        if (!empty($f['busca'])) {
            $where[] = "(p.nome LIKE :b OR p.sku LIKE :b OR p.descricao_curta LIKE :b)";
            $params[':b'] = '%' . $f['busca'] . '%';
        }
        if (!empty($f['destaque'])) {
            $where[] = "p.destaque = 1";
        }

        $whereSql = 'WHERE ' . implode(' AND ', $where);

        // ordenação
        $ord = $f['ordem'] ?? 'recentes';
        $orderMap = [
            'recentes'   => 'p.created_at DESC',
            'nome_asc'   => 'p.nome ASC',
            'nome_desc'  => 'p.nome DESC',
            'preco_asc'  => 'p.preco ASC',
            'preco_desc' => 'p.preco DESC',
            'destaque'   => 'p.destaque DESC, p.ordem ASC'
        ];
        $orderSql = 'ORDER BY ' . ($orderMap[$ord] ?? $orderMap['recentes']);

        // total
        $sqlCount = "SELECT COUNT(DISTINCT p.id) total
                     FROM produtos p
                     LEFT JOIN categorias c ON c.id = p.categoria_id
                     LEFT JOIN colecoes co ON co.id = p.colecao_id
                     {$whereSql}";
        $stmt = $this->db->prepare($sqlCount);
        $stmt->execute($params);
        $total = (int)($stmt->fetch()['total'] ?? 0);

        // lista
        $offset = ($page - 1) * $perPage;
        $sql = "SELECT p.*, c.nome AS categoria_nome, c.slug AS categoria_slug,
                       co.nome AS colecao_nome, co.slug AS colecao_slug,
                       (SELECT arquivo FROM produto_imagens
                           WHERE produto_id = p.id ORDER BY principal DESC, ordem ASC LIMIT 1) AS imagem_principal
                FROM produtos p
                LEFT JOIN categorias c ON c.id = p.categoria_id
                LEFT JOIN colecoes co ON co.id = p.colecao_id
                {$whereSql}
                {$orderSql}
                LIMIT :l OFFSET :o";

        $stmt = $this->db->prepare($sql);
        foreach ($params as $k => $v) $stmt->bindValue($k, $v);
        $stmt->bindValue(':l', $perPage, PDO::PARAM_INT);
        $stmt->bindValue(':o', $offset, PDO::PARAM_INT);
        $stmt->execute();

        return [
            'items' => $stmt->fetchAll(),
            'total' => $total,
            'pages' => (int)ceil($total / $perPage),
            'page'  => $page
        ];
    }

    /** Produtos em destaque para home */
    public function destaques(int $limit = 8): array
    {
        $stmt = $this->db->prepare(
            "SELECT p.*, (SELECT arquivo FROM produto_imagens WHERE produto_id = p.id
               ORDER BY principal DESC, ordem ASC LIMIT 1) AS imagem_principal
             FROM produtos p WHERE p.ativo = 1 AND p.destaque = 1
             ORDER BY p.ordem ASC, p.created_at DESC LIMIT :l"
        );
        $stmt->bindValue(':l', $limit, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll();
    }

    /** Produto por slug com imagens e variações */
    public function porSlug(string $slug): ?array
    {
        $stmt = $this->db->prepare(
            "SELECT p.*, c.nome AS categoria_nome, c.slug AS categoria_slug,
                    co.nome AS colecao_nome, co.slug AS colecao_slug
             FROM produtos p
             LEFT JOIN categorias c ON c.id = p.categoria_id
             LEFT JOIN colecoes co ON co.id = p.colecao_id
             WHERE p.slug = :s AND p.ativo = 1 LIMIT 1"
        );
        $stmt->execute([':s' => $slug]);
        $p = $stmt->fetch();
        if (!$p) return null;

        $p['imagens'] = $this->imagens((int)$p['id']);
        $p['variacoes'] = $this->variacoes((int)$p['id']);
        return $p;
    }

    public function imagens(int $produto_id): array
    {
        $stmt = $this->db->prepare(
            "SELECT * FROM produto_imagens WHERE produto_id = :p ORDER BY principal DESC, ordem ASC"
        );
        $stmt->execute([':p' => $produto_id]);
        return $stmt->fetchAll();
    }

    public function variacoes(int $produto_id): array
    {
        $stmt = $this->db->prepare(
            "SELECT * FROM produto_variacoes WHERE produto_id = :p AND ativo = 1 ORDER BY ordem ASC, id ASC"
        );
        $stmt->execute([':p' => $produto_id]);
        return $stmt->fetchAll();
    }

    /**
     * Produtos relacionados (pela mesma categoria, se existir)
     *
     * CORREÇÃO v1.1: separamos a query em dois caminhos para evitar
     * o erro HY093 (Invalid parameter number) quando :cat era usado
     * duas vezes na mesma SQL com EMULATE_PREPARES desligado.
     */
    public function relacionados(int $produto_id, ?int $categoria_id, int $limit = 4): array
    {
        if ($categoria_id) {
            $sql = "SELECT p.*, (SELECT arquivo FROM produto_imagens WHERE produto_id = p.id
                        ORDER BY principal DESC, ordem ASC LIMIT 1) AS imagem_principal
                    FROM produtos p
                    WHERE p.ativo = 1 AND p.id <> :id AND p.categoria_id = :cat
                    ORDER BY p.destaque DESC, RAND() LIMIT :l";
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':id',  $produto_id,   PDO::PARAM_INT);
            $stmt->bindValue(':cat', $categoria_id, PDO::PARAM_INT);
            $stmt->bindValue(':l',   $limit,        PDO::PARAM_INT);
        } else {
            $sql = "SELECT p.*, (SELECT arquivo FROM produto_imagens WHERE produto_id = p.id
                        ORDER BY principal DESC, ordem ASC LIMIT 1) AS imagem_principal
                    FROM produtos p
                    WHERE p.ativo = 1 AND p.id <> :id
                    ORDER BY p.destaque DESC, RAND() LIMIT :l";
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':id', $produto_id, PDO::PARAM_INT);
            $stmt->bindValue(':l',  $limit,      PDO::PARAM_INT);
        }
        $stmt->execute();
        return $stmt->fetchAll();
    }

    /** Admin: lista paginada com imagem principal */
    public function listarAdmin(array $f = [], int $page = 1, int $perPage = 20): array
    {
        $where = ["1=1"];
        $params = [];

        if (!empty($f['busca'])) {
            $where[] = "(p.nome LIKE :b OR p.sku LIKE :b)";
            $params[':b'] = '%' . $f['busca'] . '%';
        }
        if (isset($f['ativo']) && $f['ativo'] !== '') {
            $where[] = "p.ativo = :at";
            $params[':at'] = (int)$f['ativo'];
        }
        if (!empty($f['categoria_id'])) {
            $where[] = "p.categoria_id = :cid";
            $params[':cid'] = (int)$f['categoria_id'];
        }

        $whereSql = 'WHERE ' . implode(' AND ', $where);

        $stmt = $this->db->prepare("SELECT COUNT(*) t FROM produtos p {$whereSql}");
        $stmt->execute($params);
        $total = (int)$stmt->fetch()['t'];

        $offset = ($page - 1) * $perPage;
        $sql = "SELECT p.*, c.nome AS categoria_nome, co.nome AS colecao_nome,
                    (SELECT arquivo FROM produto_imagens WHERE produto_id = p.id ORDER BY principal DESC LIMIT 1) AS imagem_principal
                FROM produtos p
                LEFT JOIN categorias c ON c.id = p.categoria_id
                LEFT JOIN colecoes co ON co.id = p.colecao_id
                {$whereSql}
                ORDER BY p.ordem ASC, p.created_at DESC
                LIMIT :l OFFSET :o";

        $stmt = $this->db->prepare($sql);
        foreach ($params as $k => $v) $stmt->bindValue($k, $v);
        $stmt->bindValue(':l', $perPage, PDO::PARAM_INT);
        $stmt->bindValue(':o', $offset, PDO::PARAM_INT);
        $stmt->execute();

        return [
            'items' => $stmt->fetchAll(),
            'total' => $total,
            'pages' => (int)ceil($total / $perPage),
            'page'  => $page
        ];
    }

    public function adicionarImagem(int $produto_id, string $arquivo, bool $principal = false, int $ordem = 0): int
    {
        if ($principal) {
            $this->db->prepare("UPDATE produto_imagens SET principal = 0 WHERE produto_id = :p")
                     ->execute([':p' => $produto_id]);
        }
        $stmt = $this->db->prepare(
            "INSERT INTO produto_imagens (produto_id, arquivo, principal, ordem)
             VALUES (:p, :a, :pr, :o)"
        );
        $stmt->execute([
            ':p' => $produto_id,
            ':a' => $arquivo,
            ':pr' => $principal ? 1 : 0,
            ':o' => $ordem
        ]);
        return (int)$this->db->lastInsertId();
    }

    public function removerImagem(int $imagem_id): bool
    {
        $stmt = $this->db->prepare("SELECT arquivo FROM produto_imagens WHERE id = :i");
        $stmt->execute([':i' => $imagem_id]);
        $img = $stmt->fetch();
        if ($img) {
            $caminho = UPLOADS_PATH . '/' . $img['arquivo'];
            if (file_exists($caminho)) @unlink($caminho);
        }
        return $this->db->prepare("DELETE FROM produto_imagens WHERE id = :i")
                        ->execute([':i' => $imagem_id]);
    }

    public function adicionarVariacao(int $produto_id, array $dados): int
    {
        $dados['produto_id'] = $produto_id;
        $cols = array_keys($dados);
        $placeholders = array_map(fn($c)=>":{$c}", $cols);
        $sql = "INSERT INTO produto_variacoes (" . implode(',', $cols) . ") VALUES (" . implode(',', $placeholders) . ")";
        $stmt = $this->db->prepare($sql);
        $stmt->execute(array_combine($placeholders, array_values($dados)));
        return (int)$this->db->lastInsertId();
    }

    public function removerVariacao(int $var_id): bool
    {
        return $this->db->prepare("DELETE FROM produto_variacoes WHERE id = :i")
                        ->execute([':i' => $var_id]);
    }

    public function toggleAtivo(int $id): void
    {
        $this->db->prepare("UPDATE produtos SET ativo = 1 - ativo WHERE id = :i")
                 ->execute([':i' => $id]);
    }

    public function toggleDestaque(int $id): void
    {
        $this->db->prepare("UPDATE produtos SET destaque = 1 - destaque WHERE id = :i")
                 ->execute([':i' => $id]);
    }
}