import { v } from "convex/values";
import { mutation, query, action, internalMutation } from "./_generated/server";
import { Id } from "./_generated/dataModel";
import { renderizarTemplate } from "./templatesMensagens";

/**
 * Enfileirar email para envio
 */
export const enfileirarEmail = mutation({
  args: {
    destinatario: v.string(), // email
    destinatarioId: v.optional(v.id("usuarios")),
    assunto: v.string(),
    corpo: v.string(),
    templateId: v.optional(v.id("templatesMensagens")),
    enviadoPorId: v.id("usuarios"),
  },
  returns: v.object({ sucesso: v.boolean(), emailId: v.optional(v.id("notificacoesEmail")) }),
  handler: async (ctx, args) => {
    // Validar email
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(args.destinatario)) {
      return { sucesso: false };
    }

    // Adicionar à fila
    const emailId = await ctx.db.insert("notificacoesEmail", {
      destinatario: args.destinatario,
      destinatarioId: args.destinatarioId,
      assunto: args.assunto,
      corpo: args.corpo,
      templateId: args.templateId,
      status: "pendente",
      tentativas: 0,
      enviadoPor: args.enviadoPorId,
      criadoEm: Date.now(),
    });

    return { sucesso: true, emailId };
  },
});

/**
 * Enviar email usando template
 */
export const enviarEmailComTemplate = mutation({
  args: {
    destinatario: v.string(),
    destinatarioId: v.optional(v.id("usuarios")),
    templateCodigo: v.string(),
    variaveis: v.any(), // Record<string, string>
    enviadoPorId: v.id("usuarios"),
  },
  returns: v.object({ sucesso: v.boolean(), emailId: v.optional(v.id("notificacoesEmail")) }),
  handler: async (ctx, args) => {
    // Buscar template
    const template = await ctx.db
      .query("templatesMensagens")
      .withIndex("by_codigo", (q) => q.eq("codigo", args.templateCodigo))
      .first();

    if (!template) {
      console.error("Template não encontrado:", args.templateCodigo);
      return { sucesso: false };
    }

    // Renderizar template
    const assunto = renderizarTemplate(template.titulo, args.variaveis);
    const corpo = renderizarTemplate(template.corpo, args.variaveis);

    // Enfileirar email
    const emailId = await ctx.db.insert("notificacoesEmail", {
      destinatario: args.destinatario,
      destinatarioId: args.destinatarioId,
      assunto,
      corpo,
      templateId: template._id,
      status: "pendente",
      tentativas: 0,
      enviadoPor: args.enviadoPorId,
      criadoEm: Date.now(),
    });

    return { sucesso: true, emailId };
  },
});

/**
 * Listar emails na fila
 */
export const listarFilaEmails = query({
  args: {
    status: v.optional(v.union(
      v.literal("pendente"),
      v.literal("enviando"),
      v.literal("enviado"),
      v.literal("falha")
    )),
    limite: v.optional(v.number()),
  },
  returns: v.array(v.any()),
  handler: async (ctx, args) => {
    let query = ctx.db.query("notificacoesEmail");

    if (args.status) {
      query = query.withIndex("by_status", (q) => q.eq("status", args.status));
    } else {
      query = query.withIndex("by_criado_em");
    }

    const emails = await query.order("desc").take(args.limite || 100);

    return emails;
  },
});

/**
 * Reenviar email falhado
 */
export const reenviarEmail = mutation({
  args: {
    emailId: v.id("notificacoesEmail"),
  },
  returns: v.object({ sucesso: v.boolean() }),
  handler: async (ctx, args) => {
    const email = await ctx.db.get(args.emailId);
    if (!email) {
      return { sucesso: false };
    }

    // Resetar status para pendente
    await ctx.db.patch(args.emailId, {
      status: "pendente",
      tentativas: 0,
      ultimaTentativa: undefined,
      erroDetalhes: undefined,
    });

    return { sucesso: true };
  },
});

/**
 * Action para enviar email REAL usando nodemailer
 */
export const enviarEmailAction = action({
  args: {
    emailId: v.id("notificacoesEmail"),
  },
  returns: v.object({ sucesso: v.boolean(), erro: v.optional(v.string()) }),
  handler: async (ctx, args) => {
    "use node";
    
    const nodemailer = require("nodemailer");
    
    try {
      // Buscar email da fila
      const email = await ctx.runQuery(async (ctx) => {
        return await ctx.db.get(args.emailId);
      });

      if (!email) {
        return { sucesso: false, erro: "Email não encontrado" };
      }

      // Buscar configuração SMTP
      const config = await ctx.runQuery(async (ctx) => {
        return await ctx.db
          .query("configuracaoEmail")
          .withIndex("by_ativo", (q) => q.eq("ativo", true))
          .first();
      });

      if (!config) {
        return { sucesso: false, erro: "Configuração de email não encontrada ou inativa" };
      }

      if (!config.testado) {
        return { sucesso: false, erro: "Configuração SMTP não foi testada. Teste a conexão primeiro!" };
      }

      // Marcar como enviando
      await ctx.runMutation(async (ctx) => {
        await ctx.db.patch(args.emailId, {
          status: "enviando",
          tentativas: (email.tentativas || 0) + 1,
          ultimaTentativa: Date.now(),
        });
      });

      // Criar transporter do nodemailer
      const transporter = nodemailer.createTransport({
        host: config.smtpHost,
        port: config.smtpPort,
        secure: config.smtpSecure, // true para 465, false para outros
        auth: {
          user: config.smtpUser,
          pass: config.smtpPassword,
        },
        tls: {
          // Não rejeitar certificados não autorizados (útil para testes)
          rejectUnauthorized: false
        }
      });

      // Enviar email REAL
      const info = await transporter.sendMail({
        from: `"${config.remetenteNome}" <${config.remetenteEmail}>`,
        to: email.destinatario,
        subject: email.assunto,
        html: email.corpo,
      });

      console.log("✅ Email enviado com sucesso!");
      console.log("  Para:", email.destinatario);
      console.log("  Assunto:", email.assunto);
      console.log("  Message ID:", info.messageId);

      // Marcar como enviado
      await ctx.runMutation(async (ctx) => {
        await ctx.db.patch(args.emailId, {
          status: "enviado",
          enviadoEm: Date.now(),
        });
      });

      return { sucesso: true };
    } catch (error: any) {
      console.error("❌ Erro ao enviar email:", error.message);
      
      // Marcar como falha
      await ctx.runMutation(async (ctx) => {
        const email = await ctx.db.get(args.emailId);
        await ctx.db.patch(args.emailId, {
          status: "falha",
          erroDetalhes: error.message || "Erro desconhecido",
          tentativas: (email?.tentativas || 0) + 1,
        });
      });

      return { sucesso: false, erro: error.message || "Erro ao enviar email" };
    }
  },
});

/**
 * Processar fila de emails (cron job - processa emails pendentes)
 */
export const processarFilaEmails = internalMutation({
  args: {},
  returns: v.object({ processados: v.number() }),
  handler: async (ctx) => {
    // Buscar emails pendentes (max 10 por execução)
    const emailsPendentes = await ctx.db
      .query("notificacoesEmail")
      .withIndex("by_status", (q) => q.eq("status", "pendente"))
      .take(10);

    let processados = 0;

    for (const email of emailsPendentes) {
      // Verificar se não excedeu tentativas (max 3)
      if ((email.tentativas || 0) >= 3) {
        await ctx.db.patch(email._id, {
          status: "falha",
          erroDetalhes: "Número máximo de tentativas excedido",
        });
        continue;
      }

      // Agendar envio via action
      // IMPORTANTE: Não podemos chamar action diretamente de mutation
      // Por isso, usaremos o scheduler
      await ctx.scheduler.runAfter(0, "email:enviarEmailAction" as any, {
        emailId: email._id,
      });

      processados++;
    }

    console.log(`📧 Fila de emails processada: ${processados} emails agendados para envio`);

    return { processados };
  },
});


