/**
 * ============================================================
 * SERVIÇO DE BANCO DE DADOS — PostgreSQL (Self-Hosted)
 * Substitui todas as chamadas supabase.from(...) do sistema
 * ============================================================
 */
import pg from 'pg';

const DATABASE_URL = process.env.DATABASE_URL || 'postgresql://edumanager:EduManager2026!Seguro@postgres:5432/edumanager';

const pool = new pg.Pool({
  connectionString: DATABASE_URL,
  max: 20,
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 5000,
});

pool.on('error', (err) => {
  console.error('[PostgreSQL] Erro inesperado no pool:', err);
});

// ============================================================
// HELPER: Buscar school_data JSON blob (compatibilidade legada)
// ============================================================
export async function getSchoolData() {
  const { rows } = await pool.query(
    'SELECT data FROM school_data WHERE id = 1'
  );
  return rows[0]?.data || {};
}

/**
 * Percorre as aulas concluídas e gera registros de falta para alunos que não compareceram.
 * Isso transforma faltas "virtuais" em registros físicos no banco de dados.
 */
export async function processAutoAbsences(data) {
  if (!data.lessons || !data.students || !data.attendance) return data;

  const now = new Date();
  let updated = false;

  // Cache de alunos por turma para performance
  const studentsByClass = {};

  data.lessons.forEach(lesson => {
    const lessonEndStr = `${lesson.date}T${lesson.endTime || '23:59'}:00`;
    const lessonEnd = new Date(lessonEndStr);

    if (now > lessonEnd && lesson.status !== 'cancelled') {
      if (!studentsByClass[lesson.classId]) {
        studentsByClass[lesson.classId] = data.students.filter(s => s.classId === lesson.classId && s.status === 'active');
      }

      studentsByClass[lesson.classId].forEach(student => {
        const hasRecord = data.attendance.some(a => 
          a.studentId === student.id && 
          (a.lessonId === lesson.id || (a.date && a.date.startsWith(lesson.date)))
        );

        if (!hasRecord) {
          data.attendance.push({
            id: `auto-abs-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
            studentId: student.id,
            classId: lesson.classId,
            lessonId: lesson.id,
            date: `${lesson.date}T${lesson.startTime || '00:00'}:00`,
            type: 'absence',
            verified: true,
            autoGenerated: true
          });
          updated = true;
        }
      });
    }
  });

  if (updated) {
    data.lastUpdated = new Date().toISOString();
  }
  return data;
}

export async function saveSchoolData(data) {
  // Aplicar fechamento de pauta automático antes de salvar
  const dataWithAbsences = await processAutoAbsences(data);
  
  await pool.query(
    `INSERT INTO school_data (id, data, updated_at)
     VALUES (1, $1, NOW())
     ON CONFLICT (id) DO UPDATE SET data = $1, updated_at = NOW()`,
    [JSON.stringify(dataWithAbsences)]
  );
  
  // Sincronizar tabelas relacionais em background para não travar o salvamento
  syncJsonToRelationalTables(dataWithAbsences).catch(err => 
    console.error('[Database:Sync] Erro na sincronização automática:', err)
  );
}

// ============================================================
// HELPERS: alunos_cobrancas
// ============================================================
export async function insertCobrancas(cobrancas) {
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    for (const c of cobrancas) {
      await client.query(
        `INSERT INTO alunos_cobrancas 
         (aluno_id, asaas_customer_id, asaas_payment_id, asaas_installment_id, installment, valor, vencimento, link_boleto)
         VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
        [c.aluno_id, c.asaas_customer_id, c.asaas_payment_id, c.asaas_installment_id || c.installment, c.installment, c.valor, c.vencimento, c.link_boleto]
      );
    }
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
}

export async function updateCobranca(asaasPaymentId, updateData) {
  const setClauses = [];
  const values = [];
  let i = 1;

  for (const [key, value] of Object.entries(updateData)) {
    if (value !== undefined) {
      setClauses.push(`${key} = $${i}`);
      values.push(value);
      i++;
    }
  }

  if (setClauses.length === 0) return;

  values.push(asaasPaymentId);
  await pool.query(
    `UPDATE alunos_cobrancas SET ${setClauses.join(', ')} WHERE asaas_payment_id = $${i}`,
    values
  );
}

export async function deleteCobranca(asaasPaymentId) {
  await pool.query(
    'DELETE FROM alunos_cobrancas WHERE asaas_payment_id = $1',
    [asaasPaymentId]
  );
}

export async function getCobrancaByPaymentId(asaasPaymentId) {
  const { rows } = await pool.query(
    'SELECT * FROM alunos_cobrancas WHERE asaas_payment_id = $1',
    [asaasPaymentId]
  );
  return rows[0] || null;
}

export async function getCobrancasByOrQuery(id) {
  // Replicates: supabase.from('alunos_cobrancas').select('*').or(...)
  const { rows } = await pool.query(
    `SELECT * FROM alunos_cobrancas 
     WHERE installment = $1 
        OR asaas_installment_id = $1 
        OR asaas_payment_id = $1 
        OR id::text = $1
     ORDER BY vencimento ASC`,
    [id]
  );
  return rows;
}

export async function getCobrancasByAlunoId(alunoId) {
  const { rows } = await pool.query(
    'SELECT * FROM alunos_cobrancas WHERE aluno_id = $1 ORDER BY vencimento ASC',
    [alunoId]
  );
  return rows;
}

export async function getCobrancasPendentes() {
  const { rows } = await pool.query(
    "SELECT * FROM alunos_cobrancas WHERE status = 'PENDENTE'"
  );
  return rows;
}

export async function getCobrancasAtrasadas() {
  const { rows } = await pool.query(
    "SELECT * FROM alunos_cobrancas WHERE status = 'ATRASADO'"
  );
  return rows;
}

export async function getCobrancasByInstallmentId(installmentId) {
  const { rows } = await pool.query(
    'SELECT * FROM alunos_cobrancas WHERE asaas_installment_id = $1 ORDER BY vencimento ASC',
    [installmentId]
  );
  return rows;
}

export async function updateCobrancaLinkCarne(installmentId, linkCarne) {
  await pool.query(
    'UPDATE alunos_cobrancas SET link_carne = $1 WHERE asaas_installment_id = $2',
    [linkCarne, installmentId]
  );
}

export async function updateCobrancaByField(field, id, updateData) {
  const setClauses = [];
  const values = [];
  let i = 1;

  for (const [key, value] of Object.entries(updateData)) {
    if (value !== undefined) {
      setClauses.push(`${key} = $${i}`);
      values.push(value);
      i++;
    }
  }

  if (setClauses.length === 0) return;

  values.push(id);
  await pool.query(
    `UPDATE alunos_cobrancas SET ${setClauses.join(', ')} WHERE ${field} = $${i}`,
    values
  );
}

// ============================================================
// HELPERS: provas_submissoes
// ============================================================
export async function getSubmissoesByAluno(alunoId) {
  const { rows } = await pool.query(
    'SELECT * FROM provas_submissoes WHERE aluno_id = $1',
    [alunoId]
  );
  return rows;
}

export async function getSubmissaoByAlunoAndExam(alunoId, examId) {
  const { rows } = await pool.query(
    'SELECT id FROM provas_submissoes WHERE aluno_id = $1 AND prova_id = $2 LIMIT 1',
    [alunoId, examId]
  );
  return rows;
}

export async function insertSubmissao(submission) {
  await pool.query(
    `INSERT INTO provas_submissoes (aluno_id, prova_id, total_questoes, acertos, erros, percentual, nota_final, respostas, created_at)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
    [
      submission.aluno_id, submission.exam_id,
      submission.total_questions, submission.correct_count, submission.wrong_count,
      submission.percentage, submission.final_score,
      JSON.stringify(submission.answers_json), submission.created_at
    ]
  );
}

// ============================================================
// HELPERS: notas_boletim
// ============================================================
export async function initNotasTable() {
  // Remover constraints restritivas da tabela de submissões se existirem (transição JSON -> Postgres)
  try {
    await pool.query(`
      ALTER TABLE provas_submissoes DROP CONSTRAINT IF EXISTS provas_submissoes_aluno_id_fkey;
      ALTER TABLE provas_submissoes DROP CONSTRAINT IF EXISTS provas_submissoes_prova_id_fkey;
    `);
  } catch (err) {
    console.log('[PostgreSQL] ℹ️ Submissoes fkey já removidas ou tabela não existe.');
  }

  // Garantir unicidade do asaas_payment_id para permitir ON CONFLICT
  try {
    await pool.query(`
      DO $$ 
      BEGIN 
        IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'unique_asaas_payment_id') THEN
          ALTER TABLE alunos_cobrancas ADD CONSTRAINT unique_asaas_payment_id UNIQUE (asaas_payment_id);
        END IF;
      END $$;
    `);
  } catch (err) {
    console.warn('[PostgreSQL] Erro ao garantir UNIQUE em alunos_cobrancas:', err.message);
  }

  await pool.query(`
    CREATE TABLE IF NOT EXISTS notas_boletim (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      aluno_id VARCHAR(255) NOT NULL,
      disciplina_id VARCHAR(255) NOT NULL,
      periodo_id VARCHAR(255) NOT NULL,
      prova_id VARCHAR(255),
      valor NUMERIC(5, 2) NOT NULL,
      updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
      UNIQUE(aluno_id, disciplina_id, periodo_id, prova_id)
    );
  `);
}

export async function getNotasByAluno(alunoId) {
  const { rows } = await pool.query(
    'SELECT * FROM notas_boletim WHERE aluno_id = $1',
    [alunoId]
  );
  return rows;
}

export async function upsertNota(nota) {
  // Trata prova_id null se for direta para o unique index funcionar de forma previsível (PostgreSQL 15+ tem NULLS NOT DISTINCT, mas para garantir via app logic vamos usar uma abordagem de ON CONFLICT)
  // No caso do PostgreSQL padrão, múltiplos NULLs não dão conflito no UNIQUE.
  // Para contornar e permitir upsert real, faremos DELETE e INSERT ou garantiremos que o código gerencie o NULL logicamente.
  
  if (nota.prova_id) {
    await pool.query(
      `INSERT INTO notas_boletim (aluno_id, disciplina_id, periodo_id, prova_id, valor, updated_at)
       VALUES ($1, $2, $3, $4, $5, NOW())
       ON CONFLICT (aluno_id, disciplina_id, periodo_id, prova_id) 
       DO UPDATE SET valor = EXCLUDED.valor, updated_at = NOW()`,
      [nota.aluno_id, nota.disciplina_id, nota.periodo_id, nota.prova_id, nota.valor]
    );
  } else {
    // Para notas diretas, se existir apagamos e inserimos (pois o unique index normal não restringe múltiplos nulls)
    await pool.query(
      `DELETE FROM notas_boletim WHERE aluno_id = $1 AND disciplina_id = $2 AND periodo_id = $3 AND prova_id IS NULL`,
      [nota.aluno_id, nota.disciplina_id, nota.periodo_id]
    );
    await pool.query(
      `INSERT INTO notas_boletim (aluno_id, disciplina_id, periodo_id, prova_id, valor, updated_at)
       VALUES ($1, $2, $3, NULL, $4, NOW())`,
      [nota.aluno_id, nota.disciplina_id, nota.periodo_id, nota.valor]
    );
  }
}

export async function deleteNotasManuaisAusentes(alunoId, notasManuaisRetidas) {
    // Para limpar notas que o professor apagou (vazio) no manager
    // notasManuaisRetidas é um array de objetos { disciplina_id, periodo_id, prova_id }
    // Implementaremos a limpeza iterativamente na rota
}

// ============================================================
// SINCRONIZAÇÃO: JSON -> TABELAS RELACIONAIS
// Garante que IDs do JSON existam nas tabelas para evitar erro de Foreign Key
// ============================================================
export async function syncJsonToRelationalTables() {
  const client = await pool.connect();
  try {
    const data = await getSchoolData();
    if (!data) return;

    console.log('[Sincronização] 🔄 Iniciando espelhamento TOTAL (Modo Blindado)...');
    await client.query('BEGIN');

    // Garantir colunas na tabela frequencias
    await client.query(`ALTER TABLE frequencias ADD COLUMN IF NOT EXISTS justificativa TEXT`);
    await client.query(`ALTER TABLE frequencias ADD COLUMN IF NOT EXISTS justificativa_aceita BOOLEAN DEFAULT FALSE`);

    // 1. Sincronizar Cursos
    if (data.courses && Array.isArray(data.courses)) {
      const courseIds = data.courses.map(c => c.id).filter(Boolean);
      if (courseIds.length > 0) {
        await client.query('DELETE FROM cursos WHERE id != ALL($1)', [courseIds]);
      } else {
        await client.query('DELETE FROM cursos');
      }

      for (const c of data.courses) {
        if (!c.id || !c.name) continue;
        await client.query(
          `INSERT INTO cursos (id, nome, duracao, duracao_meses, taxa_matricula, mensalidade, descricao, multa_percentual, juros_percentual)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
           ON CONFLICT (id) DO UPDATE SET 
            nome = EXCLUDED.nome, duracao = EXCLUDED.duracao, duracao_meses = EXCLUDED.duracao_meses,
            taxa_matricula = EXCLUDED.taxa_matricula, mensalidade = EXCLUDED.mensalidade,
            descricao = EXCLUDED.descricao, multa_percentual = EXCLUDED.multa_percentual,
            juros_percentual = EXCLUDED.juros_percentual`,
          [c.id, c.name, c.duration || '', c.durationMonths || 0, c.registrationFee || 0, c.monthlyFee || 0, c.description || '', c.finePercentage || 0, c.interestPercentage || 0]
        );
      }
    }

    // Garantir colunas de refação em provas
    await client.query('ALTER TABLE provas ADD COLUMN IF NOT EXISTS permitir_refacao BOOLEAN DEFAULT FALSE');

    // 2. Sincronizar Disciplinas (Subjects)
    if (data.subjects && Array.isArray(data.subjects)) {
      const subIds = data.subjects.map(s => s.id).filter(Boolean);
      if (subIds.length > 0) {
        await client.query('DELETE FROM disciplinas WHERE id != ALL($1)', [subIds]);
      } else {
        await client.query('DELETE FROM disciplinas');
      }

      for (const sub of data.subjects) {
        if (!sub.id || !sub.name) continue;
        await client.query(
          `INSERT INTO disciplinas (id, nome)
           VALUES ($1, $2)
           ON CONFLICT (id) DO UPDATE SET nome = EXCLUDED.nome`,
          [sub.id, sub.name]
        );
      }
    }

    // 3. Sincronizar Períodos (Bimestres)
    if (data.periods && Array.isArray(data.periods)) {
      const periodIds = data.periods.map(p => p.id).filter(Boolean);
      if (periodIds.length > 0) {
        await client.query('DELETE FROM periodos WHERE id != ALL($1)', [periodIds]);
      } else {
        await client.query('DELETE FROM periodos');
      }

      for (const p of data.periods) {
        if (!p.id || !p.name) continue;
        await client.query(
          `INSERT INTO periodos (id, nome)
           VALUES ($1, $2)
           ON CONFLICT (id) DO UPDATE SET nome = EXCLUDED.nome`,
          [p.id, p.name]
        );
      }
    }

    // 4. Sincronizar Turmas
    if (data.classes && Array.isArray(data.classes)) {
      const classIds = data.classes.map(t => t.id).filter(Boolean);
      if (classIds.length > 0) {
        await client.query('DELETE FROM turmas WHERE id != ALL($1)', [classIds]);
      } else {
        await client.query('DELETE FROM turmas');
      }

      for (const t of data.classes) {
        if (!t.id || !t.name) continue;
        await client.query(
          `INSERT INTO turmas (id, nome, curso_id, professor, horario, dia_semana, max_alunos, data_inicio, data_fim, horario_inicio_padrao, horario_fim_padrao)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
           ON CONFLICT (id) DO UPDATE SET 
            nome = EXCLUDED.nome, curso_id = EXCLUDED.curso_id, professor = EXCLUDED.professor,
            horario = EXCLUDED.horario, dia_semana = EXCLUDED.dia_semana, max_alunos = EXCLUDED.max_alunos,
            data_inicio = EXCLUDED.data_inicio, data_fim = EXCLUDED.data_fim,
            horario_inicio_padrao = EXCLUDED.horario_inicio_padrao, horario_fim_padrao = EXCLUDED.horario_fim_padrao`,
          [t.id, t.name, t.courseId || null, t.teacher || '', t.schedule || '', t.scheduleDay || null, t.maxStudents || 30, t.startDate || null, t.endDate || null, t.defaultStartTime || null, t.defaultEndTime || null]
        );
      }
    }

    // 5. Sincronizar Alunos
    if (data.students && Array.isArray(data.students)) {
      const studentIds = data.students.map(s => s.id).filter(Boolean);
      if (studentIds.length > 0) {
        await client.query('DELETE FROM alunos WHERE id != ALL($1)', [studentIds]);
      } else {
        await client.query('DELETE FROM alunos');
      }

      for (const s of data.students) {
        if (!s.id || !s.name) continue;
        await client.query(
          `INSERT INTO alunos (
            id, nome, email, telefone, data_nascimento, cpf, rg, rg_data_emissao,
            nome_responsavel, telefone_responsavel, cpf_responsavel, data_nascimento_responsavel,
            turma_id, status, data_matricula, foto_url, cep, rua, numero, bairro, cidade, estado,
            desconto, tem_responsavel, modelo_contrato_id, numero_matricula, senha_portal
          ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27)
          ON CONFLICT (id) DO UPDATE SET 
            nome = EXCLUDED.nome, email = EXCLUDED.email, telefone = EXCLUDED.telefone, data_nascimento = EXCLUDED.data_nascimento,
            cpf = EXCLUDED.cpf, rg = EXCLUDED.rg, rg_data_emissao = EXCLUDED.rg_data_emissao,
            nome_responsavel = EXCLUDED.nome_responsavel, telefone_responsavel = EXCLUDED.telefone_responsavel,
            cpf_responsavel = EXCLUDED.cpf_responsavel, data_nascimento_responsavel = EXCLUDED.data_nascimento_responsavel,
            turma_id = EXCLUDED.turma_id, status = EXCLUDED.status, data_matricula = EXCLUDED.data_matricula,
            foto_url = EXCLUDED.foto_url, cep = EXCLUDED.cep, rua = EXCLUDED.rua, numero = EXCLUDED.numero,
            bairro = EXCLUDED.bairro, cidade = EXCLUDED.cidade, estado = EXCLUDED.estado,
            desconto = EXCLUDED.desconto, tem_responsavel = EXCLUDED.tem_responsavel,
            modelo_contrato_id = EXCLUDED.modelo_contrato_id, numero_matricula = EXCLUDED.numero_matricula,
            senha_portal = EXCLUDED.senha_portal`,
          [
            s.id, s.name, s.email || '', s.phone || '', s.birthDate || null, s.cpf || '', s.rg || '', s.rgIssueDate || null,
            s.guardianName || '', s.guardianPhone || '', s.guardianCpf || '', s.guardianBirthDate || null,
            s.classId || null, s.status || 'active', s.registrationDate || null, s.photo || '',
            s.addressZip || '', s.addressStreet || '', s.addressNumber || '', s.addressNeighborhood || '', s.addressCity || '', s.addressState || '',
            s.discount || 0, s.hasGuardian || false, s.contractTemplateId || null, s.enrollmentNumber || null, s.portalPassword || null
          ]
        );
      }
    }

    // 6. Sincronizar Provas
    if (data.exams && Array.isArray(data.exams)) {
      const examIds = data.exams.map(e => e.id).filter(Boolean);
      if (examIds.length > 0) {
        await client.query('DELETE FROM provas WHERE id != ALL($1)', [examIds]);
      } else {
        await client.query('DELETE FROM provas');
      }

      for (const e of data.exams) {
        if (!e.id || !e.title) continue;
        await client.query(
          `INSERT INTO provas (id, turma_id, disciplina_id, periodo_id, titulo, duracao_minutos, status, permitir_refacao)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
           ON CONFLICT (id) DO UPDATE SET 
            turma_id = EXCLUDED.turma_id, disciplina_id = EXCLUDED.disciplina_id, periodo_id = EXCLUDED.periodo_id,
            titulo = EXCLUDED.titulo, duracao_minutos = EXCLUDED.duracao_minutos, status = EXCLUDED.status,
            permitir_refacao = EXCLUDED.permitir_refacao`,
          [e.id, e.classId || null, e.subjectId || null, e.periodId || null, e.title, e.durationMinutes || 60, e.status || 'draft', e.allowRetake || false]
        ).catch(err => console.warn(`[Sync:Provas] Erro na prova ${e.id}:`, err.message));
      }
    }

    // 7. Sincronizar Frequências
    if (data.attendance && Array.isArray(data.attendance)) {
      const attIds = data.attendance.map(f => f.id).filter(Boolean);
      if (attIds.length > 0) {
        await client.query('DELETE FROM frequencias WHERE id != ALL($1)', [attIds]);
      } else {
        await client.query('DELETE FROM frequencias');
      }

      for (const f of data.attendance) {
        if (!f.id || !f.studentId || !f.classId) continue;
        await client.query(
          `INSERT INTO frequencias (id, aluno_id, turma_id, data, foto, verificado, tipo, justificativa, justificativa_aceita)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
           ON CONFLICT (id) DO UPDATE SET 
            aluno_id = EXCLUDED.aluno_id, turma_id = EXCLUDED.turma_id, data = EXCLUDED.data,
            foto = EXCLUDED.foto, verificado = EXCLUDED.verificado, tipo = EXCLUDED.tipo,
            justificativa = EXCLUDED.justificativa, justificativa_aceita = EXCLUDED.justificativa_aceita`,
          [f.id, f.studentId, f.classId, f.date, f.photo || '', f.verified || false, f.type || 'presence', f.justification || null, f.justificationAccepted || false]
        );
      }
    }

    // 8. Sincronizar Cobranças (Financeiro) — com campos ricos para migração SQL-First
    if (data.payments && Array.isArray(data.payments)) {
      for (const p of data.payments) {
        if (!p.asaasPaymentId || !p.studentId) continue;
        
        // Normalizar status para o padrão SQL (maiúsculas)
        const rawStatus = (p.status || 'pending').toLowerCase();
        const statusMap = { 'paid': 'PAGO', 'received': 'PAGO', 'confirmed': 'PAGO', 'overdue': 'ATRASADO', 'cancelled': 'CANCELADO' };
        const sqlStatus = statusMap[rawStatus] || 'PENDENTE';

        await client.query(
          `INSERT INTO alunos_cobrancas (
            aluno_id, asaas_payment_id, asaas_installment_id, installment, 
            valor, vencimento, link_boleto, status,
            description, type, discount, installment_number, total_installments,
            contract_id, asaas_payment_url, amount_original, data_pagamento
          ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
          ON CONFLICT (asaas_payment_id) DO UPDATE SET 
            aluno_id = EXCLUDED.aluno_id,
            asaas_installment_id = COALESCE(EXCLUDED.asaas_installment_id, alunos_cobrancas.asaas_installment_id),
            installment = COALESCE(EXCLUDED.installment, alunos_cobrancas.installment),
            valor = EXCLUDED.valor,
            vencimento = EXCLUDED.vencimento,
            link_boleto = COALESCE(EXCLUDED.link_boleto, alunos_cobrancas.link_boleto),
            status = CASE WHEN alunos_cobrancas.status = 'PAGO' THEN alunos_cobrancas.status ELSE EXCLUDED.status END,
            description = COALESCE(EXCLUDED.description, alunos_cobrancas.description),
            type = COALESCE(EXCLUDED.type, alunos_cobrancas.type),
            discount = COALESCE(EXCLUDED.discount, alunos_cobrancas.discount),
            installment_number = COALESCE(EXCLUDED.installment_number, alunos_cobrancas.installment_number),
            total_installments = COALESCE(EXCLUDED.total_installments, alunos_cobrancas.total_installments),
            contract_id = COALESCE(EXCLUDED.contract_id, alunos_cobrancas.contract_id),
            asaas_payment_url = COALESCE(EXCLUDED.asaas_payment_url, alunos_cobrancas.asaas_payment_url),
            amount_original = COALESCE(EXCLUDED.amount_original, alunos_cobrancas.amount_original),
            data_pagamento = COALESCE(EXCLUDED.data_pagamento, alunos_cobrancas.data_pagamento)`,
          [
            p.studentId, 
            p.asaasPaymentId, 
            p.asaasInstallmentId || p.installmentId || null, 
            p.installment || null,
            p.amount || 0, 
            p.dueDate, 
            p.bankSlipUrl || p.link || null, 
            sqlStatus,
            p.description || null,
            p.type || 'monthly',
            p.discount || 0,
            p.installmentNumber || null,
            p.totalInstallments || null,
            p.contractId || null,
            p.asaasPaymentUrl || null,
            p.amount || null,
            p.paidDate || null
          ]
        ).catch(err => console.warn(`[Sync:Finance] Erro no boleto ${p.asaasPaymentId}:`, err.message));
      }
    }

    await client.query('COMMIT');
    console.log('[Sincronização] 🚀 Espelhamento TOTAL concluído com sucesso!');
  } catch (err) {
    await client.query('ROLLBACK');
    console.error('[Sincronização] ❌ Erro Crítico:', err.message);
  } finally {
    client.release();
  }
}

// ============================================================
// EXPORT POOL para queries diretas quando necessário
// ============================================================
export { pool };
export default pool;
