<?php
namespace Modules\GestorContratos\Services;

use PDO;
use Exception;

/**
 * Serviço de integração com outros módulos do ERP
 * Integra contratos com Vendas, Financeiro, Clientes e Fornecedores
 */
class IntegracaoService {
    private PDO $pdo;
    private string $tenantId;

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

    /**
     * Gera contrato automaticamente a partir de um pedido de venda
     */
    public function gerarContratoDeVenda(int $vendaId, ?int $modeloId = null): int {
        try {
            $this->pdo->beginTransaction();

            // Buscar dados do pedido
            $stmt = $this->pdo->prepare('
                SELECT so.*, c.id as cliente_id, c.nome as cliente_nome, c.email as cliente_email,
                       c.cpf_cnpj as cliente_cpf_cnpj, c.telefone as cliente_telefone
                FROM sales_orders so
                LEFT JOIN clients c ON so.cliente_id = c.id
                WHERE so.id = ? AND so.tenant_id = ?
            ');
            $stmt->execute([$vendaId, $this->tenantId]);
            $venda = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$venda) {
                throw new Exception('Pedido de venda não encontrado');
            }

            // Buscar itens do pedido
            $stmt = $this->pdo->prepare('
                SELECT soi.*, p.nome as produto_nome, p.codigo as produto_codigo
                FROM sales_order_items soi
                LEFT JOIN products p ON soi.product_id = p.id
                WHERE soi.sales_order_id = ?
                ORDER BY soi.numero_item
            ');
            $stmt->execute([$vendaId]);
            $itens = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Buscar modelo se fornecido, senão buscar modelo padrão de venda
            $modelo = null;
            if ($modeloId) {
                $stmt = $this->pdo->prepare('SELECT * FROM contratos_modelos WHERE id = ? AND tenant_id = ?');
                $stmt->execute([$modeloId, $this->tenantId]);
                $modelo = $stmt->fetch(PDO::FETCH_ASSOC);
            } else {
                $stmt = $this->pdo->prepare('
                    SELECT * FROM contratos_modelos 
                    WHERE categoria = "venda" AND ativo = 1 AND tenant_id = ?
                    ORDER BY id DESC LIMIT 1
                ');
                $stmt->execute([$this->tenantId]);
                $modelo = $stmt->fetch(PDO::FETCH_ASSOC);
            }

            if (!$modelo) {
                throw new Exception('Modelo de contrato não encontrado');
            }

            // Preparar variáveis
            $variaveis = [
                'NOME_CLIENTE' => $venda['cliente_nome'] ?? '',
                'EMAIL_CLIENTE' => $venda['cliente_email'] ?? '',
                'CPF_CNPJ_CLIENTE' => $venda['cliente_cpf_cnpj'] ?? '',
                'TELEFONE_CLIENTE' => $venda['cliente_telefone'] ?? '',
                'NUMERO_PEDIDO' => $venda['numero'] ?? '',
                'DATA_PEDIDO' => $venda['data_pedido'] ? date('d/m/Y', strtotime($venda['data_pedido'])) : date('d/m/Y'),
                'VALOR_TOTAL' => number_format($venda['valor_total'] ?? 0, 2, ',', '.'),
                'VALOR_CONTRATO' => number_format($venda['valor_total'] ?? 0, 2, ',', '.'),
                'DATA_ATUAL' => date('d/m/Y'),
                'DATA_ATUAL_EXTENSO' => $this->dataPorExtenso(date('Y-m-d')),
            ];

            // Preparar itens do pedido
            $itensHtml = '<table style="width:100%; border-collapse: collapse; margin: 20px 0;">
                <thead>
                    <tr style="background-color: #f5f5f5;">
                        <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Item</th>
                        <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Produto</th>
                        <th style="border: 1px solid #ddd; padding: 8px; text-align: right;">Quantidade</th>
                        <th style="border: 1px solid #ddd; padding: 8px; text-align: right;">Valor Unit.</th>
                        <th style="border: 1px solid #ddd; padding: 8px; text-align: right;">Total</th>
                    </tr>
                </thead>
                <tbody>';
            
            foreach ($itens as $item) {
                $itensHtml .= '<tr>
                    <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars($item['numero_item']) . '</td>
                    <td style="border: 1px solid #ddd; padding: 8px;">' . htmlspecialchars($item['produto_nome'] ?? '') . '</td>
                    <td style="border: 1px solid #ddd; padding: 8px; text-align: right;">' . number_format($item['quantidade'] ?? 0, 2, ',', '.') . '</td>
                    <td style="border: 1px solid #ddd; padding: 8px; text-align: right;">R$ ' . number_format($item['valor_unitario'] ?? 0, 2, ',', '.') . '</td>
                    <td style="border: 1px solid #ddd; padding: 8px; text-align: right;">R$ ' . number_format($item['valor_total'] ?? 0, 2, ',', '.') . '</td>
                </tr>';
            }
            
            $itensHtml .= '</tbody></table>';
            $variaveis['ITENS_PEDIDO'] = $itensHtml;

            // Buscar dados da empresa
            $dadosEmpresa = $this->buscarDadosEmpresa();
            $variaveis = array_merge($variaveis, $dadosEmpresa);

            // Preencher modelo
            $editorService = new EditorService($this->tenantId);
            $conteudoHtml = $editorService->preencherVariaveis($modelo['conteudo_html'], $variaveis);

            // Criar contrato
            $contratoService = new ContratoService($this->tenantId);
            $contratoId = $contratoService->criarContrato([
                'titulo' => 'Contrato de Venda - Pedido ' . $venda['numero'],
                'tipo' => 'venda',
                'modelo_id' => $modelo['id'],
                'cliente_id' => $venda['cliente_id'],
                'venda_id' => $vendaId,
                'conteudo_html' => $conteudoHtml,
                'variaveis_preenchidas' => $variaveis,
                'valor_total' => $venda['valor_total'],
                'data_inicio' => date('Y-m-d'),
                'status' => 'rascunho',
                'signatarios' => [
                    [
                        'nome' => $venda['cliente_nome'] ?? 'Cliente',
                        'email' => $venda['cliente_email'] ?? '',
                        'cpf_cnpj' => $venda['cliente_cpf_cnpj'] ?? '',
                        'tipo' => 'externo',
                        'ordem' => 1
                    ]
                ]
            ]);

            // Vincular contrato ao pedido
            $stmt = $this->pdo->prepare('UPDATE sales_orders SET contrato_id = ? WHERE id = ?');
            $stmt->execute([$contratoId, $vendaId]);

            $this->pdo->commit();
            return $contratoId;
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw new Exception('Erro ao gerar contrato de venda: ' . $e->getMessage());
        }
    }

    /**
     * Gera contrato automaticamente a partir de uma conta a receber/pagar
     */
    public function gerarContratoFinanceiro(int $financeiroId, string $tipo, ?int $modeloId = null): int {
        try {
            $this->pdo->beginTransaction();

            // Buscar dados financeiros
            $tabela = $tipo === 'receber' ? 'contas_receber' : 'contas_pagar';
            $stmt = $this->pdo->prepare("
                SELECT cr.*, c.id as cliente_id, c.nome as cliente_nome, c.email as cliente_email,
                       c.cpf_cnpj as cliente_cpf_cnpj
                FROM {$tabela} cr
                LEFT JOIN clients c ON cr.cliente_id = c.id
                WHERE cr.id = ? AND cr.tenant_id = ?
            ");
            $stmt->execute([$financeiroId, $this->tenantId]);
            $financeiro = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$financeiro) {
                throw new Exception('Conta financeira não encontrada');
            }

            // Buscar modelo
            $modelo = null;
            if ($modeloId) {
                $stmt = $this->pdo->prepare('SELECT * FROM contratos_modelos WHERE id = ? AND tenant_id = ?');
                $stmt->execute([$modeloId, $this->tenantId]);
                $modelo = $stmt->fetch(PDO::FETCH_ASSOC);
            } else {
                $categoria = $tipo === 'receber' ? 'recebimento' : 'pagamento';
                $stmt = $this->pdo->prepare("
                    SELECT * FROM contratos_modelos 
                    WHERE categoria = ? AND ativo = 1 AND tenant_id = ?
                    ORDER BY id DESC LIMIT 1
                ");
                $stmt->execute([$categoria, $this->tenantId]);
                $modelo = $stmt->fetch(PDO::FETCH_ASSOC);
            }

            if (!$modelo) {
                throw new Exception('Modelo de contrato não encontrado');
            }

            // Preparar variáveis
            $variaveis = [
                'NOME_CLIENTE' => $financeiro['cliente_nome'] ?? '',
                'EMAIL_CLIENTE' => $financeiro['cliente_email'] ?? '',
                'CPF_CNPJ_CLIENTE' => $financeiro['cliente_cpf_cnpj'] ?? '',
                'VALOR_TOTAL' => number_format($financeiro['valor'] ?? 0, 2, ',', '.'),
                'VALOR_CONTRATO' => number_format($financeiro['valor'] ?? 0, 2, ',', '.'),
                'DATA_VENCIMENTO' => $financeiro['data_vencimento'] ? date('d/m/Y', strtotime($financeiro['data_vencimento'])) : '',
                'DATA_ATUAL' => date('d/m/Y'),
                'DATA_ATUAL_EXTENSO' => $this->dataPorExtenso(date('Y-m-d')),
            ];

            // Buscar dados da empresa
            $dadosEmpresa = $this->buscarDadosEmpresa();
            $variaveis = array_merge($variaveis, $dadosEmpresa);

            // Preencher modelo
            $editorService = new EditorService($this->tenantId);
            $conteudoHtml = $editorService->preencherVariaveis($modelo['conteudo_html'], $variaveis);

            // Criar contrato
            $contratoService = new ContratoService($this->tenantId);
            $contratoId = $contratoService->criarContrato([
                'titulo' => 'Contrato ' . ($tipo === 'receber' ? 'de Recebimento' : 'de Pagamento') . ' - ' . ($financeiro['numero'] ?? ''),
                'tipo' => $tipo,
                'modelo_id' => $modelo['id'],
                'cliente_id' => $financeiro['cliente_id'] ?? null,
                'financeiro_id' => $financeiroId,
                'conteudo_html' => $conteudoHtml,
                'variaveis_preenchidas' => $variaveis,
                'valor_total' => $financeiro['valor'] ?? 0,
                'data_inicio' => date('Y-m-d'),
                'status' => 'rascunho'
            ]);

            $this->pdo->commit();
            return $contratoId;
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw new Exception('Erro ao gerar contrato financeiro: ' . $e->getMessage());
        }
    }

    /**
     * Busca dados da empresa para preencher variáveis
     */
    private function buscarDadosEmpresa(): array {
        try {
            $stmt = $this->pdo->prepare('
                SELECT * FROM empresas 
                WHERE tenant_id = ? AND principal = 1
                LIMIT 1
            ');
            $stmt->execute([$this->tenantId]);
            $empresa = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$empresa) {
                return [];
            }

            return [
                'NOME_EMPRESA' => $empresa['nome'] ?? '',
                'CNPJ_EMPRESA' => $empresa['cnpj'] ?? '',
                'EMAIL_EMPRESA' => $empresa['email'] ?? '',
                'TELEFONE_EMPRESA' => $empresa['telefone'] ?? '',
                'ENDERECO_EMPRESA' => $empresa['endereco'] ?? '',
                'CIDADE_EMPRESA' => $empresa['cidade'] ?? '',
                'ESTADO_EMPRESA' => $empresa['estado'] ?? '',
                'CEP_EMPRESA' => $empresa['cep'] ?? '',
            ];
        } catch (Exception $e) {
            return [];
        }
    }

    /**
     * Converte data para extenso
     */
    private function dataPorExtenso(string $data): string {
        $meses = [
            1 => 'janeiro', 2 => 'fevereiro', 3 => 'março', 4 => 'abril',
            5 => 'maio', 6 => 'junho', 7 => 'julho', 8 => 'agosto',
            9 => 'setembro', 10 => 'outubro', 11 => 'novembro', 12 => 'dezembro'
        ];

        $timestamp = strtotime($data);
        $dia = date('d', $timestamp);
        $mes = (int)date('m', $timestamp);
        $ano = date('Y', $timestamp);

        return $dia . ' de ' . $meses[$mes] . ' de ' . $ano;
    }

    /**
     * Vincula contrato assinado a uma conta a receber/pagar
     */
    public function vincularContratoFinanceiro(int $contratoId, int $financeiroId, string $tipo): bool {
        try {
            $tabela = $tipo === 'receber' ? 'contas_receber' : 'contas_pagar';
            
            // Verificar se a tabela tem coluna contrato_id
            $stmt = $this->pdo->query("SHOW COLUMNS FROM {$tabela} LIKE 'contrato_id'");
            if (!$stmt->fetch()) {
                // Adicionar coluna se não existir
                $this->pdo->exec("ALTER TABLE {$tabela} ADD COLUMN contrato_id BIGINT UNSIGNED NULL");
                $this->pdo->exec("ALTER TABLE {$tabela} ADD INDEX idx_contrato (contrato_id)");
            }

            $stmt = $this->pdo->prepare("UPDATE {$tabela} SET contrato_id = ? WHERE id = ?");
            $stmt->execute([$contratoId, $financeiroId]);

            // Atualizar contrato
            $stmt = $this->pdo->prepare('
                UPDATE contratos 
                SET financeiro_id = ? 
                WHERE id = ? AND tenant_id = ?
            ');
            $stmt->execute([$financeiroId, $contratoId, $this->tenantId]);

            return true;
        } catch (Exception $e) {
            throw new Exception('Erro ao vincular contrato financeiro: ' . $e->getMessage());
        }
    }
}

