<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

require_once(dirname(__DIR__) . '/config/db.php');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
header('Content-Type: application/json; charset=utf-8');

function safeJson($data) {
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
}

try {
    $acao = $_GET['ajax'] ?? null;

    // ==============================================
    // 🔹 CRUD DE VARIÁVEIS (LISTAR / SALVAR / TOGGLE / EXCLUIR)
    // ==============================================
    if ($acao === 'listar_variaveis') {
        $sql = "SELECT cdvariavel, nome, tipo, modelo, flativo, dthrcriacao, ordem, grafico,
                       fl_origem, cdintegracao, fl_agregar_calc
                  FROM back.variavel
              ORDER BY cdvariavel DESC";
        $rows = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
        safeJson(['ok' => true, 'data' => $rows]);
    }

    if ($acao === 'salvar_variavel') {
        $dados = json_decode(file_get_contents('php://input'), true);
        if (!$dados) safeJson(['ok' => false, 'msg' => '❌ Dados inválidos.']);

        $nome   = trim($dados['nome'] ?? '');
        $tipo   = trim($dados['tipo'] ?? '');
        $modelo = trim($dados['modelo'] ?? '');
        $ordem  = isset($dados['ordem']) && $dados['ordem'] !== '' ? (int)$dados['ordem'] : null;
        $grafico = filter_var($dados['grafico'] ?? '', FILTER_VALIDATE_BOOLEAN) ?: false;
        $fl_origem = filter_var($dados['fl_origem'] ?? false, FILTER_VALIDATE_BOOLEAN) ?: false;
        $cdintegracao = $fl_origem && !empty($dados['cdintegracao']) ? (int)$dados['cdintegracao'] : null;
        $fl_agregar_calc = $fl_origem ? (filter_var($dados['fl_agregar_calc'] ?? false, FILTER_VALIDATE_BOOLEAN) ?: false) : false;

        if ($nome === '' || $tipo === '' || $modelo === '') {
            safeJson(['ok' => false, 'msg' => '❌ Informe nome, tipo e modelo da variável.']);
        }

        // Validar valores permitidos para modelo
        if (!in_array($modelo, ['meta', 'orcamento', 'submeta', 'resultado'])) {
            safeJson(['ok' => false, 'msg' => '❌ Modelo deve ser "meta", "submeta", "orcamento" ou "resultado".']);
        }

        // Para Dashboard / Relatorio / Outro, a ordem é obrigatória
        if ($tipo !== 'Planejamento') {
            if ($ordem === null || $ordem <= 0) {
                safeJson(['ok' => false, 'msg' => '❌ Informe a ordem prioritária (número inteiro > 0).']);
            }
        } else {
            // Planejamento não usa ordem
            $ordem = null;
        }

        // Validação: se fl_origem ativo, deve ter integração selecionada
        if ($fl_origem && !$cdintegracao) {
            safeJson(['ok' => false, 'msg' => '❌ Selecione uma integração de origem para apresentar os dados.']);
        }

        $sql = "INSERT INTO back.variavel (nome, tipo, modelo, flativo, ordem, grafico, fl_origem, cdintegracao, fl_agregar_calc)
                VALUES (:nome, :tipo, :modelo, 0, :ordem, :grafico, :fl_origem, :cdintegracao, :fl_agregar_calc)
                RETURNING cdvariavel";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([
            ':nome' => $nome, 
            ':tipo' => $tipo, 
            ':modelo' => $modelo, 
            ':ordem' => $ordem, 
            ':grafico' => (int)$grafico,
            ':fl_origem' => $fl_origem ? 'true' : 'false',
            ':cdintegracao' => $cdintegracao,
            ':fl_agregar_calc' => $fl_agregar_calc ? 'true' : 'false'
        ]);

        // Salvar empresas vinculadas
        $cdvariavelNovo = (int)$stmt->fetchColumn();
        $empresas = $dados['empresas'] ?? [];
        if (is_array($empresas) && !empty($empresas)) {
            $stIns = $pdo->prepare("INSERT INTO back.variavel_empresa (cdvariavel, cdempresa) VALUES (:var, :emp)");
            foreach ($empresas as $empId) {
                $stIns->execute([':var' => $cdvariavelNovo, ':emp' => (int)$empId]);
            }
        }

        safeJson(['ok' => true, 'msg' => '✅ Variável criada com sucesso.']);
    }

    if ($acao === 'obter_variavel') {
        $id = (int)($_GET['cdvariavel'] ?? 0);
        if ($id <= 0) safeJson(['ok' => false, 'msg' => '❌ ID inválido.']);

        $sql = "SELECT cdvariavel, nome, tipo, modelo, ordem, grafico,
                       fl_origem, cdintegracao, fl_agregar_calc
                  FROM back.variavel
                 WHERE cdvariavel = :id";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([':id' => $id]);
        $variavel = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$variavel) {
            safeJson(['ok' => false, 'msg' => '❌ Variável não encontrada.']);
        }

        // Buscar empresas vinculadas
        $stEmps = $pdo->prepare("SELECT cdempresa FROM back.variavel_empresa WHERE cdvariavel = :id ORDER BY cdempresa");
        $stEmps->execute([':id' => $id]);
        $variavel['empresas'] = array_map('intval', $stEmps->fetchAll(PDO::FETCH_COLUMN));

        safeJson(['ok' => true, 'data' => $variavel]);
    }

    if ($acao === 'atualizar_variavel') {
        $dados = json_decode(file_get_contents('php://input'), true);
        if (!$dados) safeJson(['ok' => false, 'msg' => '❌ Dados inválidos.']);

        $cdvariavel = (int)($dados['cdvariavel'] ?? 0);
        $nome   = trim($dados['nome'] ?? '');
        $tipo   = trim($dados['tipo'] ?? '');
        $modelo = trim($dados['modelo'] ?? '');
        $ordem  = isset($dados['ordem']) && $dados['ordem'] !== '' ? (int)$dados['ordem'] : null;
        $grafico = filter_var($dados['grafico'] ?? '', FILTER_VALIDATE_BOOLEAN) ?: false;
        $fl_origem = filter_var($dados['fl_origem'] ?? false, FILTER_VALIDATE_BOOLEAN) ?: false;
        $cdintegracao = $fl_origem && !empty($dados['cdintegracao']) ? (int)$dados['cdintegracao'] : null;
        $fl_agregar_calc = $fl_origem ? (filter_var($dados['fl_agregar_calc'] ?? false, FILTER_VALIDATE_BOOLEAN) ?: false) : false;

        if ($cdvariavel <= 0) {
            safeJson(['ok' => false, 'msg' => '❌ ID de variável inválido.']);
        }

        if ($nome === '' || $tipo === '' || $modelo === '') {
            safeJson(['ok' => false, 'msg' => '❌ Informe nome, tipo e modelo da variável.']);
        }

        // Validar valores permitidos para modelo
        if (!in_array($modelo, ['meta', 'orcamento', 'submeta', 'resultado'])) {
            safeJson(['ok' => false, 'msg' => '❌ Modelo deve ser "meta", "submeta", "orcamento" ou "resultado".']);
        }

        // Para Dashboard / Relatorio / Outro, a ordem é obrigatória
        if ($tipo !== 'Planejamento') {
            if ($ordem === null || $ordem <= 0) {
                safeJson(['ok' => false, 'msg' => '❌ Informe a ordem prioritária (número inteiro > 0).']);
            }
        } else {
            // Planejamento não usa ordem
            $ordem = null;
        }

        // Validação: se fl_origem ativo, deve ter integração selecionada
        if ($fl_origem && !$cdintegracao) {
            safeJson(['ok' => false, 'msg' => '❌ Selecione uma integração de origem para apresentar os dados.']);
        }

        $sql = "UPDATE back.variavel
                   SET nome = :nome, tipo = :tipo, modelo = :modelo, ordem = :ordem, grafico = :grafico,
                       fl_origem = :fl_origem, cdintegracao = :cdintegracao, fl_agregar_calc = :fl_agregar_calc
                 WHERE cdvariavel = :id";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([
            ':nome' => $nome,
            ':tipo' => $tipo,
            ':modelo' => $modelo,
            ':ordem' => $ordem,
            ':grafico' => (int)$grafico,
            ':fl_origem' => $fl_origem ? 'true' : 'false',
            ':cdintegracao' => $cdintegracao,
            ':fl_agregar_calc' => $fl_agregar_calc ? 'true' : 'false',
            ':id' => $cdvariavel
        ]);

        // Atualizar empresas vinculadas
        $pdo->prepare("DELETE FROM back.variavel_empresa WHERE cdvariavel = :var")->execute([':var' => $cdvariavel]);
        $empresas = $dados['empresas'] ?? [];
        if (is_array($empresas) && !empty($empresas)) {
            $stIns = $pdo->prepare("INSERT INTO back.variavel_empresa (cdvariavel, cdempresa) VALUES (:var, :emp)");
            foreach ($empresas as $empId) {
                $stIns->execute([':var' => $cdvariavel, ':emp' => (int)$empId]);
            }
        }

        safeJson(['ok' => true, 'msg' => '✅ Variável atualizada com sucesso.']);
    }

    if ($acao === 'toggle_variavel') {
        $id = (int)($_POST['cdvariavel'] ?? 0);
        if ($id <= 0) safeJson(['ok' => false, 'msg' => '❌ ID inválido.']);

        $sql = "UPDATE back.variavel
                    SET flativo = CASE WHEN flativo = 0 THEN 1 ELSE 0 END
                  WHERE cdvariavel = :id";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([':id' => $id]);

        safeJson(['ok' => true, 'msg' => '✅ Status alterado.']);
    }

    if ($acao === 'excluir_variavel') {
        $id = (int)($_POST['cdvariavel'] ?? 0);
        if ($id <= 0) safeJson(['ok' => false, 'msg' => '❌ ID inválido.']);

        try {
            $pdo->beginTransaction();

            // Remove seções vinculadas
            $stmt = $pdo->prepare("DELETE FROM back.variavel_secao WHERE cdvariavel = :id");
            $stmt->execute([':id' => $id]);

            // Remove a própria variável
            $stmt = $pdo->prepare("DELETE FROM back.variavel WHERE cdvariavel = :id");
            $stmt->execute([':id' => $id]);

            $pdo->commit();
            safeJson(['ok' => true, 'msg' => '🗑️ Variável excluída com sucesso.']);
        } catch (Exception $e) {
            if ($pdo->inTransaction()) {
                $pdo->rollBack();
            }
            safeJson(['ok' => false, 'msg' => '❌ Não foi possível excluir a variável: ' . $e->getMessage()]);
        }
    }

    // ==============================================
    // 🔹 LISTAR SEÇÕES
    // ==============================================
    if ($acao === 'listar_secoes') {
        $cdvariavel = (int)($_GET['cdvariavel'] ?? 0);
        if ($cdvariavel <= 0) safeJson([]);

        $sql = "SELECT s.cdsecao, s.cdvariavel, s.ordem, s.titulo, s.mascara, s.formula, s.flativo
                  FROM back.variavel_secao s
                 WHERE s.cdvariavel = :v
              ORDER BY s.ordem";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([':v' => $cdvariavel]);
        safeJson($stmt->fetchAll(PDO::FETCH_ASSOC));
    }

    // ==============================================
    // 🔹 OBTER DESCRIÇÃO DE CONTA (para preview)
    // ==============================================
    if ($acao === 'getConta') {
        $id = (int)($_GET['cdcontacontabil'] ?? 0);
        if ($id <= 0) safeJson(['ok' => false]);
        $stmt = $pdo->prepare("SELECT dsconta FROM back.planocontabil WHERE cdcontacontabil = :id");
        $stmt->execute([':id' => $id]);
        $ds = $stmt->fetchColumn();
        safeJson(['ok' => (bool)$ds, 'dsconta' => $ds ?: null]);
    }

    // ==============================================
    // 🔹 SALVAR SEÇÃO
    // ==============================================
    if ($acao === 'salvar_secao') {
        $dados = json_decode(file_get_contents('php://input'), true);
        if (!$dados) safeJson(['ok' => false, 'msg' => '❌ Dados inválidos.']);

        $cdvariavel = (int)($dados['cdvariavel'] ?? 0);
        $ordem      = (int)($dados['ordem'] ?? 0);
        $titulo     = trim($dados['titulo'] ?? '');
        $mascara    = trim($dados['mascara'] ?? '');
        $formula    = trim($dados['formula'] ?? '');
        $flativo    = 0;

        if ($cdvariavel <= 0)
            safeJson(['ok' => false, 'msg' => '❌ Variável não informada.']);
        if (!$ordem || !$titulo || !$mascara || !$formula)
            safeJson(['ok' => false, 'msg' => '❌ Preencha todos os campos obrigatórios.']);

        // 🔹 Substitui e normaliza símbolos e espaços
        $formula = str_replace(['÷', '×'], ['/', '*'], $formula);
        $formula = preg_replace('/\s+/', ' ', trim($formula));

        // 🔹 Valida caracteres permitidos
        if (preg_match('/[^0-9\+\-\*\/\(\)\s]/', $formula))
            safeJson(['ok' => false, 'msg' => '❌ A fórmula contém caracteres inválidos. Use apenas números, operadores e parênteses.']);

        // 🔹 Valida operadores soltos
        if (preg_match('/^[\+\-\*\/]/', $formula) || preg_match('/[\+\-\*\/]$/', $formula))
            safeJson(['ok' => false, 'msg' => '⚠️ A fórmula não pode começar nem terminar com operador.']);
        if (preg_match('/[\+\-\*\/]\s*[\+\-\*\/]/', $formula))
            safeJson(['ok' => false, 'msg' => '⚠️ Operadores duplicados encontrados.']);

        // 🔹 Operadores obrigatórios entre contas
        if (preg_match('/(\d+)\s+(\d+)/', $formula))
            safeJson(['ok' => false, 'msg' => '❌ Insira um operador entre as contas.']);

        // 🔹 Parênteses balanceados
        $abertos = substr_count($formula, '(');
        $fechados = substr_count($formula, ')');
        if ($abertos !== $fechados)
            safeJson(['ok' => false, 'msg' => '⚠️ Parênteses abertos e fechados não estão balanceados.']);

        // 🔹 Verifica existência real das contas (corrigido com reindexação)
        preg_match_all('/\d+/', $formula, $nums);
        if (!empty($nums[0])) {
            $ids = array_unique($nums[0]);
            $placeholders = implode(',', array_fill(0, count($ids), '?'));
            $check = $pdo->prepare("SELECT cdcontacontabil FROM back.planocontabil WHERE cdcontacontabil IN ($placeholders)");
            $check->execute(array_values($ids)); // ✅ FIX: reindexa o array
            $existentes = $check->fetchAll(PDO::FETCH_COLUMN);
            $faltando = array_diff($ids, $existentes);
            if (!empty($faltando))
                safeJson(['ok' => false, 'msg' => '⚠️ As seguintes contas não existem: ' . implode(', ', $faltando)]);
        }

        // 🔹 Verifica duplicidade de ordem
        $stmt = $pdo->prepare("SELECT cdsecao FROM back.variavel_secao WHERE cdvariavel = :v AND ordem = :o");
        $stmt->execute([':v' => $cdvariavel, ':o' => $ordem]);
        $existe = $stmt->fetchColumn();

        if ($existe) {
            // Atualiza seção existente
            $sql = "UPDATE back.variavel_secao
                       SET titulo = :t, mascara = :m, formula = :f
                     WHERE cdsecao = :id";
            $stmt = $pdo->prepare($sql);
            $stmt->execute([
                ':t' => $titulo,
                ':m' => $mascara,
                ':f' => $formula,
                ':id' => $existe
            ]);
            safeJson(['ok' => true, 'msg' => '✅ Seção atualizada com sucesso!']);
        } else {
            // Insere nova seção (valida ordem duplicada)
            $stmt = $pdo->prepare("SELECT COUNT(*) FROM back.variavel_secao WHERE cdvariavel = :v AND ordem = :o");
            $stmt->execute([':v' => $cdvariavel, ':o' => $ordem]);
            if ($stmt->fetchColumn() > 0)
                safeJson(['ok' => false, 'msg' => '⚠️ Já existe uma seção com essa ordem.']);

            $sql = "INSERT INTO back.variavel_secao (cdvariavel, ordem, titulo, mascara, formula, flativo, dthcriacao)
                    VALUES (:v, :o, :t, :m, :f, :a, NOW())";
            $stmt = $pdo->prepare($sql);
            $stmt->execute([
                ':v' => $cdvariavel,
                ':o' => $ordem,
                ':t' => $titulo,
                ':m' => $mascara,
                ':f' => $formula,
                ':a' => $flativo
            ]);
            safeJson(['ok' => true, 'msg' => '✅ Seção criada com sucesso!']);
        }
    }

    // ==============================================
    // 🔹 EXCLUIR SEÇÃO (com validação de sequência)
    // ==============================================
    if ($acao === 'delete') {
        $id = (int)($_GET['id'] ?? 0);
        if ($id <= 0) safeJson(['ok' => false, 'msg' => '❌ ID inválido.']);

        // Busca a seção e variável associada
        $stmt = $pdo->prepare("SELECT cdvariavel, ordem FROM back.variavel_secao WHERE cdsecao = :id");
        $stmt->execute([':id' => $id]);
        $secao = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$secao) safeJson(['ok' => false, 'msg' => '❌ Seção não encontrada.']);

        // Verifica se existem seções posteriores (não pode excluir antes delas)
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM back.variavel_secao 
                               WHERE cdvariavel = :v AND ordem > :o");
        $stmt->execute([':v' => $secao['cdvariavel'], ':o' => $secao['ordem']]);
        $posteriores = $stmt->fetchColumn();

        if ($posteriores > 0) {
            safeJson(['ok' => false, 'msg' => '⚠️ Não é permitido excluir esta seção antes das subsequentes.']);
        }

        // Pode excluir (é a última ou única)
        $pdo->prepare("DELETE FROM back.variavel_secao WHERE cdsecao = :id")->execute([':id' => $id]);
        safeJson(['ok' => true, 'msg' => '🗑️ Seção excluída com sucesso!']);
    }

    // ==============================================
    // 🔹 VALIDAR TIPO DO VALOR DE ORIGEM (para flag agregar cálculo)
    // ==============================================
    if ($acao === 'validar_tipo_valor_origem') {
        $cdintegracao = (int)($_GET['cdintegracao'] ?? 0);
        if ($cdintegracao <= 0) safeJson(['ok' => false, 'msg' => '❌ ID de integração inválido.']);

        // Busca valores existentes na origem_dados para essa integração
        $stmt = $pdo->prepare("SELECT valor FROM back.origem_dados WHERE cdintegracao = :id AND valor IS NOT NULL AND TRIM(valor) <> '' LIMIT 100");
        $stmt->execute([':id' => $cdintegracao]);
        $valores = $stmt->fetchAll(PDO::FETCH_COLUMN);

        if (empty($valores)) {
            // Sem dados importados ainda — permite marcar otimistamente
            safeJson(['ok' => true, 'tipo' => 'numerico', 'msg' => 'Nenhum dado importado ainda. Será validado na próxima sincronização.']);
        }

        // Classifica: verifica se todos são numéricos
        $todosNumericos = true;
        $algumData = false;
        foreach ($valores as $val) {
            $val = trim($val);
            if ($val === '') continue;
            // Aceitar inteiro, decimal (ponto ou vírgula), negativo
            $normalizado = str_replace(',', '.', $val);
            if (!is_numeric($normalizado)) {
                $todosNumericos = false;
                // Tenta detectar data (formatos comuns)
                if (strtotime($val) !== false || preg_match('/^\d{2}[\/-]\d{2}[\/-]\d{4}$/', $val) || preg_match('/^\d{4}[\/-]\d{2}[\/-]\d{2}$/', $val)) {
                    $algumData = true;
                }
            }
        }

        if ($todosNumericos) {
            safeJson(['ok' => true, 'tipo' => 'numerico']);
        } elseif ($algumData) {
            safeJson(['ok' => true, 'tipo' => 'data']);
        } else {
            safeJson(['ok' => true, 'tipo' => 'texto']);
        }
    }

    // ==============================================
    // 🔹 ERRO GENÉRICO
    // ==============================================
    safeJson(['ok' => false, 'msg' => 'Ação desconhecida.']);

} catch (Exception $e) {
    safeJson(['ok' => false, 'msg' => '❌ Erro geral: ' . $e->getMessage()]);
}
