<?php

namespace Modules\Fiscal\Services;

use Gestoreasy\Core\Tenant\ConnectionManager;
use PDO;
use Exception;

/**
 * Serviço para busca de CEST (Código Especificador da Substituição Tributária) baseado em NCM
 */
class CestService {
    private PDO $pdo;

    public function __construct() {
        $this->pdo = ConnectionManager::forTenant();
        $this->ensureTable();
    }

    /**
     * Garante que a tabela de mapeamento NCM->CEST existe
     */
    private function ensureTable(): void {
        try {
            $this->pdo->exec("
                CREATE TABLE IF NOT EXISTS fiscal_ncm_cest (
                    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                    ncm VARCHAR(8) NOT NULL,
                    cest VARCHAR(7) NOT NULL,
                    descricao TEXT NULL,
                    ativo BOOLEAN NOT NULL DEFAULT TRUE,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                    INDEX idx_ncm (ncm),
                    INDEX idx_cest (cest),
                    INDEX idx_ncm_cest (ncm, cest),
                    UNIQUE KEY uk_ncm_cest (ncm, cest)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            ");
            
            // Inserir dados iniciais se a tabela estiver vazia
            $stmt = $this->pdo->query("SELECT COUNT(*) as total FROM fiscal_ncm_cest");
            $count = $stmt->fetch(PDO::FETCH_ASSOC)['total'] ?? 0;
            
            if ($count == 0) {
                $this->populateInitialData();
            }
        } catch (Exception $e) {
            // Ignorar se a tabela já existir ou houver erro
        }
    }

    /**
     * Popula dados iniciais de mapeamento NCM->CEST
     * Baseado na tabela oficial da Receita Federal
     */
    private function populateInitialData(): void {
        // Mapeamentos mais comuns NCM->CEST
        // Fonte: Anexo XI da Convenção ICMS 142/2018 e atualizações
        $mapeamentos = [
            // Bebidas
            ['22021000', '2800100', 'Água mineral, gasosa ou não'],
            ['22029000', '2800100', 'Outras águas'],
            ['22030000', '2800200', 'Cervejas'],
            ['22041000', '2800300', 'Vinhos'],
            ['22042100', '2800300', 'Vinhos espumantes'],
            ['22042900', '2800300', 'Outros vinhos'],
            
            // Refrigerantes
            ['22021000', '2800400', 'Refrigerantes'],
            ['22029000', '2800400', 'Refrigerantes'],
            
            // Cigarros
            ['24022000', '2800500', 'Cigarros'],
            ['24029000', '2800500', 'Outros cigarros'],
            
            // Combustíveis
            ['27101259', '2800600', 'Gasolina'],
            ['27101251', '2800600', 'Gasolina'],
            ['27101921', '2800700', 'Diesel'],
            ['27101929', '2800700', 'Diesel'],
            
            // Produtos de limpeza
            ['34011190', '2800800', 'Sabões e detergentes'],
            ['34011900', '2800800', 'Outros sabões'],
            ['34012000', '2800800', 'Detergentes'],
            
            // Produtos alimentícios
            ['19059090', '2800900', 'Biscoitos e bolachas'],
            ['19053100', '2800900', 'Biscoitos doces'],
            ['19053200', '2800900', 'Biscoitos salgados'],
            
            // Bebidas alcoólicas
            ['22083000', '2801000', 'Aguardente'],
            ['22084000', '2801000', 'Rum'],
            ['22085000', '2801000', 'Gin'],
            ['22086000', '2801000', 'Vodka'],
            ['22087000', '2801000', 'Licores'],
            
            // Produtos de higiene pessoal
            ['33030000', '2801100', 'Perfumes'],
            ['33041000', '2801200', 'Produtos de maquiagem'],
            ['33049900', '2801200', 'Outros cosméticos'],
            ['33051000', '2801300', 'Xampus'],
            ['33052000', '2801300', 'Condicionadores'],
            
            // Autopeças (genéricas)
            ['87089900', '2801400', 'Autopeças'],
            ['87084099', '2801400', 'Autopeças'],
            
            // ==== MOTOPEÇAS - Peças de Motocicletas ====
            ['87141000', '2801401', 'Peças de motocicletas - Cilindros e cabeçotes'],
            ['87142000', '2801401', 'Peças de motocicletas - Carburadores e injeção'],
            ['87149100', '2801401', 'Peças de motocicletas - Pneus e câmaras'],
            ['87149200', '2801401', 'Peças de motocicletas - Freios e discos'],
            ['87149300', '2801401', 'Peças de motocicletas - Amortecedores'],
            ['87149400', '2801401', 'Peças de motocicletas - Corrente e pinhão'],
            ['87149500', '2801401', 'Peças de motocicletas - Retrovisores'],
            ['87149600', '2801401', 'Peças de motocicletas - Bancos'],
            ['87149900', '2801401', 'Peças de motocicletas - Outras peças'],
            ['85112000', '2801401', 'Sistemas de ignição para motocicletas'],
            ['85118000', '2801401', 'Partes de sistemas elétricos de motocicletas'],
            ['84831000', '2801401', 'Válvulas para motocicletas'],
            ['84099100', '2801401', 'Partes de motores para motocicletas'],
            ['84139000', '2801401', 'Partes de bombas para motocicletas'],
            ['84212300', '2801401', 'Filtros de óleo para motocicletas'],
            ['84213100', '2801401', 'Filtros de ar para motocicletas'],
            ['84836000', '2801401', 'Juntas para motocicletas'],
            ['84839000', '2801401', 'Outras juntas e gaxetas para motocicletas'],
            
            // ==== AUTOPEÇAS - Peças Automotivas ====
            ['87082900', '2801402', 'Peças de carroceria'],
            ['87083000', '2801402', 'Freios e suas partes'],
            ['87084010', '2801402', 'Caixas de transmissão para veículos'],
            ['87084090', '2801402', 'Outras transmissões para veículos'],
            ['87085000', '2801402', 'Eixos e rodas para veículos'],
            ['87086000', '2801402', 'Suspensões para veículos'],
            ['87087000', '2801402', 'Radiadores para veículos'],
            ['87088000', '2801402', 'Silenciosos e tubos de escape'],
            ['87089100', '2801402', 'Embreagens e suas partes'],
            ['87089200', '2801402', 'Volantes e colunas de direção'],
            ['87089300', '2801402', 'Caixas de direção'],
            ['87089400', '2801402', 'Árvores de transmissão'],
            ['87089500', '2801402', 'Rodas e suas partes'],
            ['87089900', '2801402', 'Outras peças e acessórios'],
            ['84099100', '2801402', 'Partes de motores para veículos'],
            ['84133000', '2801402', 'Bombas de combustível'],
            ['84135000', '2801402', 'Bombas de água'],
            ['84143000', '2801402', 'Ventiladores e turbocompressores'],
            ['84149000', '2801402', 'Partes de compressores e turbocompressores'],
            ['84831000', '2801402', 'Válvulas para motores'],
            ['84832000', '2801402', 'Rolamentos para veículos'],
            ['84833000', '2801402', 'Juntas para motores'],
            ['84834000', '2801402', 'Arruelas de pressão'],
            ['84839000', '2801402', 'Outras juntas e gaxetas'],
            ['85071000', '2801402', 'Baterias para veículos'],
            ['85112000', '2801402', 'Sistemas de ignição'],
            ['85118000', '2801402', 'Partes de sistemas elétricos'],
            ['85123000', '2801402', 'Lâmpadas para veículos'],
            ['85124000', '2801402', 'Faróis e lanternas'],
            ['85272100', '2801402', 'Rádios para veículos'],
            ['85362000', '2801402', 'Fusíveis para veículos'],
            ['85365000', '2801402', 'Interruptores para veículos'],
            ['87071000', '2801402', 'Capôs e para-choques'],
            ['87081000', '2801402', 'Para-brisas e vidros'],
            ['87082100', '2801402', 'Assentos para veículos'],
            ['87082200', '2801402', 'Partes de assentos'],
            ['87082300', '2801402', 'Cintos de segurança'],
            ['87083100', '2801402', 'Pastilhas de freio'],
            ['87083200', '2801402', 'Discos de freio'],
            ['87083300', '2801402', 'Tambores de freio'],
            ['87083400', '2801402', 'Lonas de freio'],
            ['87083900', '2801402', 'Outras partes de freios'],
            ['40011000', '2801402', 'Pneus para carros'],
            ['40012100', '2801402', 'Pneus para caminhões'],
            ['40013000', '2801402', 'Câmaras de ar'],
            ['40111000', '2801402', 'Pneus para motocicletas'],
            ['40112000', '2801402', 'Pneus para bicicletas'],
            ['40116000', '2801402', 'Outros pneus'],
            ['40129000', '2801402', 'Outras partes de pneus'],
            ['40131000', '2801402', 'Correias de transmissão'],
            ['40139000', '2801402', 'Outras correias'],
            ['40161000', '2801402', 'Mangueiras e tubos'],
            ['40169000', '2801402', 'Outras peças de borracha'],
            ['84212300', '2801402', 'Filtros de óleo'],
            ['84213100', '2801402', 'Filtros de ar'],
            ['84213900', '2801402', 'Outros filtros'],
            ['84133000', '2801402', 'Bombas de óleo'],
            ['84135000', '2801402', 'Bombas de direção hidráulica'],
            ['84143000', '2801402', 'Turbocompressores'],
            ['84149000', '2801402', 'Partes de turbocompressores'],
            ['84831000', '2801402', 'Válvulas de admissão'],
            ['84832000', '2801402', 'Válvulas de escape'],
            ['84833000', '2801402', 'Válvulas de retenção'],
            ['84834000', '2801402', 'Válvulas de controle'],
            ['84835000', '2801402', 'Válvulas de segurança'],
            ['84836000', '2801402', 'Válvulas solenoides'],
            ['84839000', '2801402', 'Outras válvulas'],
            
            // ==== LOCADORA - Serviços de Locação de Veículos ====
            // NCM para serviços de locação (não há CEST específico, mas há NCMs relacionados)
            ['86090000', '2801403', 'Serviços de transporte - Locação de veículos'],
            ['77121000', '2801403', 'Aluguel de veículos automotores'],
            ['49011000', '2801403', 'Documentos e contratos de locação'],
            ['49019900', '2801403', 'Outros documentos de locação'],
            // NCMs relacionados a serviços de manutenção da frota
            ['87089900', '2801403', 'Peças para manutenção de frota'],
            ['85287200', '2801403', 'Equipamentos de rastreamento'],
            ['85311000', '2801403', 'Alarmes para veículos'],
            ['85318000', '2801403', 'Sistemas de segurança'],
            // NCMs relacionados a serviços de limpeza e higienização
            ['34011190', '2801403', 'Produtos de limpeza para veículos'],
            ['34012000', '2801403', 'Detergentes para veículos'],
            ['34013000', '2801403', 'Ceras e polimentos'],
            // NCMs relacionados a combustíveis (frota)
            ['27101259', '2801403', 'Gasolina para frota'],
            ['27101251', '2801403', 'Gasolina aditivada'],
            ['27101921', '2801403', 'Diesel para frota'],
            ['27101929', '2801403', 'Diesel S10'],
            // NCMs relacionados a pneus e acessórios
            ['40011000', '2801403', 'Pneus para locação'],
            ['40012100', '2801403', 'Pneus para caminhões'],
            ['40013000', '2801403', 'Câmaras de ar'],
            ['40161000', '2801403', 'Mangueiras e tubos'],
            // NCMs relacionados a sistemas de pagamento e gestão
            ['85287200', '2801403', 'Sistemas de pagamento'],
            ['85234900', '2801403', 'Mídias para sistemas'],
            ['84713000', '2801403', 'Computadores para gestão'],
            ['84714100', '2801403', 'Servidores para gestão'],
            
            // Eletrônicos
            ['85171200', '2801500', 'Telefones celulares'],
            ['85171300', '2801500', 'Smartphones'],
            ['85287200', '2801600', 'Monitores'],
            ['85287210', '2801600', 'Monitores LCD'],
            
            // Roupas e calçados
            ['64039900', '2801700', 'Calçados'],
            ['64041900', '2801700', 'Calçados esportivos'],
            ['61091000', '2801800', 'Camisetas'],
            ['61102000', '2801800', 'Suéteres'],
            
            // Materiais de construção
            ['69089000', '2801900', 'Cerâmicas'],
            ['69079100', '2801900', 'Azulejos'],
            ['69079200', '2801900', 'Ladrilhos'],
            
            // Produtos farmacêuticos
            ['30049099', '2802000', 'Medicamentos'],
            ['30041011', '2802000', 'Antibióticos'],
            ['30042029', '2802000', 'Vitaminas'],
            
            // Mais mapeamentos comuns
            // Bebidas não alcoólicas
            ['22011000', '2800400', 'Águas, incluindo águas minerais'],
            ['22019000', '2800400', 'Outras águas'],
            
            // Alimentos processados
            ['16041400', '2802100', 'Salsichas e embutidos'],
            ['16010000', '2802100', 'Carnes e miudezas'],
            
            // Laticínios
            ['04011000', '2802200', 'Leite pasteurizado'],
            ['04012000', '2802200', 'Leite UHT'],
            ['04022100', '2802200', 'Leite em pó'],
            
            // Óleos e gorduras
            ['15091000', '2802300', 'Óleo de oliva'],
            ['15121900', '2802300', 'Óleo de soja'],
            ['15141100', '2802300', 'Óleo de palma'],
            
            // Açúcar
            ['17011400', '2802400', 'Açúcar cristal'],
            ['17019900', '2802400', 'Açúcar refinado'],
            
            // Cigarros e produtos do tabaco
            ['24022000', '2800500', 'Cigarros'],
            ['24029000', '2800500', 'Charutos e outros produtos do tabaco'],
            
            // Produtos de papel
            ['48101300', '2802500', 'Papel higiênico'],
            ['48101900', '2802500', 'Papel toalha'],
            
            // Produtos de plástico
            ['39249000', '2802600', 'Utensílios de plástico'],
            ['39241000', '2802600', 'Copos de plástico'],
            
            // Produtos têxteis
            ['63079000', '2802700', 'Roupas de cama'],
            ['63049200', '2802700', 'Travesseiros'],
            
            // Equipamentos elétricos
            ['85165000', '2802800', 'Secadores de cabelo'],
            ['85163100', '2802800', 'Chapinhas'],
        ];
        
        $stmt = $this->pdo->prepare("
            INSERT INTO fiscal_ncm_cest (ncm, cest, descricao, ativo)
            VALUES (?, ?, ?, TRUE)
            ON DUPLICATE KEY UPDATE descricao = COALESCE(VALUES(descricao), descricao), ativo = TRUE
        ");
        
        foreach ($mapeamentos as $map) {
            try {
                $ncm = preg_replace('/[^0-9]/', '', $map[0]);
                $cest = preg_replace('/[^0-9]/', '', $map[1]);
                $descricao = $map[2] ?? null;
                
                // Validar NCM (mínimo 4 dígitos, máximo 8)
                // Validar CEST (7 dígitos)
                if (strlen($ncm) >= 4 && strlen($ncm) <= 8 && strlen($cest) == 7) {
                    // Garantir que NCM tenha 8 dígitos (preencher com zeros à direita se necessário)
                    $ncm = str_pad(substr($ncm, 0, 8), 8, '0', STR_PAD_RIGHT);
                    $stmt->execute([$ncm, $cest, $descricao]);
                }
            } catch (Exception $e) {
                // Ignorar erros de inserção (duplicatas, etc.)
            }
        }
    }

    /**
     * Busca CESTs sugeridos para um NCM
     * 
     * @param string $ncm Código NCM (8 dígitos)
     * @return array Lista de CESTs sugeridos
     */
    public function buscarCestPorNcm(string $ncm): array {
        // Limpar NCM (apenas números)
        $ncm = preg_replace('/[^0-9]/', '', $ncm);
        
        if (strlen($ncm) < 4) {
            return [];
        }
        
        $resultados = [];
        
        // Buscar correspondência exata (8 dígitos)
        if (strlen($ncm) >= 8) {
            $stmt = $this->pdo->prepare("
                SELECT DISTINCT cest, descricao
                FROM fiscal_ncm_cest
                WHERE ncm = ? AND ativo = TRUE
                ORDER BY cest
            ");
            $stmt->execute([substr($ncm, 0, 8)]);
            $exatos = $stmt->fetchAll(PDO::FETCH_ASSOC);
            foreach ($exatos as $row) {
                $resultados[] = [
                    'cest' => $row['cest'],
                    'descricao' => $row['descricao'],
                    'tipo' => 'exato'
                ];
            }
        }
        
        // Buscar por prefixo de 6 dígitos (se NCM tem 6+ dígitos e ainda não temos muitos resultados)
        if (strlen($ncm) >= 6) {
            // Coletar CESTs já encontrados para evitar duplicatas
            $cestsJaEncontrados = array_map(function($r) { return $r['cest']; }, $resultados);
            
            if (empty($cestsJaEncontrados)) {
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT cest, descricao
                    FROM fiscal_ncm_cest
                    WHERE ncm LIKE ? AND ativo = TRUE
                    ORDER BY cest
                    LIMIT 10
                ");
                $prefixo6 = substr($ncm, 0, 6) . '%';
                $stmt->execute([$prefixo6]);
            } else {
                $placeholders = str_repeat('?,', count($cestsJaEncontrados));
                $placeholders = rtrim($placeholders, ',');
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT cest, descricao
                    FROM fiscal_ncm_cest
                    WHERE ncm LIKE ? AND ativo = TRUE
                    AND cest NOT IN ($placeholders)
                    ORDER BY cest
                    LIMIT 10
                ");
                $prefixo6 = substr($ncm, 0, 6) . '%';
                $params = array_merge([$prefixo6], $cestsJaEncontrados);
                $stmt->execute($params);
            }
            
            $prefixo6Results = $stmt->fetchAll(PDO::FETCH_ASSOC);
            foreach ($prefixo6Results as $row) {
                if (count($resultados) >= 10) break;
                $resultados[] = [
                    'cest' => $row['cest'],
                    'descricao' => $row['descricao'],
                    'tipo' => 'prefixo_6'
                ];
            }
        }
        
        // Buscar por prefixo de 4 dígitos (se NCM tem 4+ dígitos e ainda não temos muitos resultados)
        if (strlen($ncm) >= 4 && count($resultados) < 10) {
            // Coletar CESTs já encontrados para evitar duplicatas
            $cestsJaEncontrados = array_map(function($r) { return $r['cest']; }, $resultados);
            
            if (empty($cestsJaEncontrados)) {
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT cest, descricao
                    FROM fiscal_ncm_cest
                    WHERE ncm LIKE ? AND ativo = TRUE
                    ORDER BY cest
                    LIMIT 10
                ");
                $prefixo4 = substr($ncm, 0, 4) . '%';
                $stmt->execute([$prefixo4]);
            } else {
                $placeholders = str_repeat('?,', count($cestsJaEncontrados));
                $placeholders = rtrim($placeholders, ',');
                $stmt = $this->pdo->prepare("
                    SELECT DISTINCT cest, descricao
                    FROM fiscal_ncm_cest
                    WHERE ncm LIKE ? AND ativo = TRUE
                    AND cest NOT IN ($placeholders)
                    ORDER BY cest
                    LIMIT 10
                ");
                $prefixo4 = substr($ncm, 0, 4) . '%';
                $params = array_merge([$prefixo4], $cestsJaEncontrados);
                $stmt->execute($params);
            }
            
            $prefixo4Results = $stmt->fetchAll(PDO::FETCH_ASSOC);
            foreach ($prefixo4Results as $row) {
                if (count($resultados) >= 10) break;
                $resultados[] = [
                    'cest' => $row['cest'],
                    'descricao' => $row['descricao'],
                    'tipo' => 'prefixo_4'
                ];
            }
        }
        
        // Remover duplicados mantendo a ordem
        $cestsVistos = [];
        $resultadosUnicos = [];
        foreach ($resultados as $resultado) {
            if (!in_array($resultado['cest'], $cestsVistos)) {
                $cestsVistos[] = $resultado['cest'];
                $resultadosUnicos[] = $resultado;
            }
        }
        
        return array_slice($resultadosUnicos, 0, 10);
    }

    /**
     * Busca todos os CESTs disponíveis (para autocomplete)
     */
    public function listarCests(?string $busca = null): array {
        $sql = "SELECT DISTINCT cest, descricao FROM fiscal_ncm_cest WHERE ativo = TRUE";
        $params = [];
        
        if ($busca) {
            $sql .= " AND (cest LIKE ? OR descricao LIKE ?)";
            $params[] = "%$busca%";
            $params[] = "%$busca%";
        }
        
        $sql .= " ORDER BY cest LIMIT 100";
        
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Adiciona ou atualiza mapeamento NCM->CEST
     */
    public function adicionarMapeamento(string $ncm, string $cest, ?string $descricao = null): bool {
        try {
            $ncm = preg_replace('/[^0-9]/', '', $ncm);
            $cest = preg_replace('/[^0-9]/', '', $cest);
            
            if (strlen($ncm) < 4 || strlen($cest) < 7) {
                return false;
            }
            
            $stmt = $this->pdo->prepare("
                INSERT INTO fiscal_ncm_cest (ncm, cest, descricao, ativo)
                VALUES (?, ?, ?, TRUE)
                ON DUPLICATE KEY UPDATE 
                    descricao = COALESCE(?, descricao),
                    ativo = TRUE,
                    updated_at = CURRENT_TIMESTAMP
            ");
            
            return $stmt->execute([substr($ncm, 0, 8), substr($cest, 0, 7), $descricao, $descricao]);
        } catch (Exception $e) {
            return false;
        }
    }
    
    /**
     * Carrega NCMs específicos para setores automotivos (MOTOPEÇAS, AUTOPEÇAS, LOCADORA)
     * Este método pode ser chamado pelos módulos addon para garantir que os NCMs estão cadastrados
     */
    public function carregarNcmsSetoresAutomotivos(): void {
        $this->populateInitialData(); // Os NCMs específicos já estão no populateInitialData
    }
    
    /**
     * Busca NCMs sugeridos por setor (MOTOPEÇAS, AUTOPEÇAS, LOCADORA)
     * 
     * @param string $setor Setor: 'motopecas', 'autopecas', 'locadora'
     * @return array Lista de NCMs com suas descrições
     */
    public function buscarNcmsPorSetor(string $setor): array {
        $cestMap = [
            'motopecas' => '2801401',
            'autopecas' => '2801402',
            'locadora' => '2801403'
        ];
        
        if (!isset($cestMap[$setor])) {
            return [];
        }
        
        $cest = $cestMap[$setor];
        
        $stmt = $this->pdo->prepare("
            SELECT DISTINCT ncm, descricao
            FROM fiscal_ncm_cest
            WHERE cest = ? AND ativo = TRUE
            ORDER BY ncm
        ");
        $stmt->execute([$cest]);
        
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

