<?php

namespace Modules\IA\Services;

use PDO;
use Exception;

/**
 * Serviço para recomendações de produtos
 */
class RecomendacoesService {
    private PDO $pdo;
    private string $tenantId;

    public function __construct(string $tenantId) {
        $this->tenantId = $tenantId;
        $this->pdo = \Gestoreasy\Core\Tenant\ConnectionManager::forTenant($tenantId);
    }

    /**
     * Obtém recomendações baseadas em um produto
     */
    public function getRecomendacoesProduto(int $productId, int $limite = 5): array {
        // Buscar produtos frequentemente comprados juntos
        $stmt = $this->pdo->prepare('
            SELECT 
                soi2.product_id,
                p.nome,
                p.preco,
                COUNT(*) as frequencia,
                SUM(soi2.quantidade) as total_vendido
            FROM sales_order_items soi1
            INNER JOIN sales_orders so ON soi1.order_id = so.id
            INNER JOIN sales_order_items soi2 ON so.id = soi2.order_id
            INNER JOIN products p ON soi2.product_id = p.id
            WHERE soi1.product_id = ?
            AND soi2.product_id != ?
            AND so.status = "finalizado"
            GROUP BY soi2.product_id, p.nome, p.preco
            ORDER BY frequencia DESC, total_vendido DESC
            LIMIT ?
        ');
        $stmt->execute([$productId, $productId, $limite]);
        $produtos = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $recomendacoes = [];
        foreach ($produtos as $produto) {
            $score = $this->calcularScoreRecomendacao($produto['frequencia'], $produto['total_vendido']);
            
            $recomendacoes[] = [
                'product_id' => (int)$produto['product_id'],
                'nome' => $produto['nome'],
                'preco' => (float)$produto['preco'],
                'score' => $score,
                'tipo' => 'frequentemente_comprado',
                'frequencia' => (int)$produto['frequencia']
            ];
        }

        return $recomendacoes;
    }

    /**
     * Obtém recomendações baseadas em um cliente
     */
    public function getRecomendacoesCliente(int $clienteId, int $limite = 5): array {
        // Buscar produtos similares aos que o cliente já comprou
        $stmt = $this->pdo->prepare('
            SELECT 
                p.id,
                p.nome,
                p.preco,
                COUNT(DISTINCT so.id) as vezes_comprado,
                SUM(soi.quantidade) as total_comprado
            FROM sales_orders so
            INNER JOIN sales_order_items soi ON so.id = soi.order_id
            INNER JOIN products p ON soi.product_id = p.id
            WHERE so.client_id = ?
            AND so.status = "finalizado"
            GROUP BY p.id, p.nome, p.preco
            ORDER BY vezes_comprado DESC, total_comprado DESC
            LIMIT 10
        ');
        $stmt->execute([$clienteId]);
        $produtosComprados = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (empty($produtosComprados)) {
            // Se cliente não tem histórico, recomendar produtos mais vendidos
            return $this->getProdutosMaisVendidos($limite);
        }

        // Buscar produtos similares
        $produtoIds = array_column($produtosComprados, 'id');
        $placeholders = implode(',', array_fill(0, count($produtoIds), '?'));
        
        $stmt = $this->pdo->prepare("
            SELECT 
                p.id,
                p.nome,
                p.preco,
                COUNT(*) as score
            FROM products p
            INNER JOIN sales_order_items soi ON p.id = soi.product_id
            INNER JOIN sales_orders so ON soi.order_id = so.id
            WHERE soi.product_id NOT IN ({$placeholders})
            AND so.id IN (
                SELECT DISTINCT so2.id
                FROM sales_orders so2
                INNER JOIN sales_order_items soi2 ON so2.id = soi2.order_id
                WHERE soi2.product_id IN ({$placeholders})
            )
            GROUP BY p.id, p.nome, p.preco
            ORDER BY score DESC
            LIMIT ?
        ");
        $params = array_merge($produtoIds, $produtoIds, [$limite]);
        $stmt->execute($params);
        $recomendacoes = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $resultado = [];
        foreach ($recomendacoes as $rec) {
            $resultado[] = [
                'product_id' => (int)$rec['id'],
                'nome' => $rec['nome'],
                'preco' => (float)$rec['preco'],
                'score' => (float)$rec['score'],
                'tipo' => 'baseado_historico'
            ];
        }

        return $resultado;
    }

    /**
     * Obtém produtos mais vendidos
     */
    private function getProdutosMaisVendidos(int $limite): array {
        $stmt = $this->pdo->prepare('
            SELECT 
                p.id,
                p.nome,
                p.preco,
                SUM(soi.quantidade) as total_vendido
            FROM products p
            INNER JOIN sales_order_items soi ON p.id = soi.product_id
            INNER JOIN sales_orders so ON soi.order_id = so.id
            WHERE so.status = "finalizado"
            GROUP BY p.id, p.nome, p.preco
            ORDER BY total_vendido DESC
            LIMIT ?
        ');
        $stmt->execute([$limite]);
        $produtos = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $resultado = [];
        foreach ($produtos as $produto) {
            $resultado[] = [
                'product_id' => (int)$produto['id'],
                'nome' => $produto['nome'],
                'preco' => (float)$produto['preco'],
                'score' => (float)$produto['total_vendido'],
                'tipo' => 'tendencia'
            ];
        }

        return $resultado;
    }

    /**
     * Calcula score de recomendação
     */
    private function calcularScoreRecomendacao(int $frequencia, float $totalVendido): float {
        // Score baseado em frequência e volume
        $scoreFrequencia = min(1, $frequencia / 10); // Normalizar até 10 compras
        $scoreVolume = min(1, $totalVendido / 100); // Normalizar até 100 unidades
        
        $score = ($scoreFrequencia * 0.6) + ($scoreVolume * 0.4);
        return round($score, 4);
    }
}

