"use node";

import { action } from "../_generated/server";
import { v } from "convex/values";
import { internal } from "../_generated/api";
import { decryptSMTPPasswordNode } from "./utils/nodeCrypto";
import nodemailer from "nodemailer";

export const enviar = action({
  args: {
    emailId: v.id("notificacoesEmail"),
  },
  returns: v.object({ sucesso: v.boolean(), erro: v.optional(v.string()) }),
  handler: async (ctx, args) => {
    "use node";

    let email;
    try {
      // Buscar email da fila
      email = await ctx.runQuery(internal.email.getEmailById, {
        emailId: args.emailId,
      });

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

      // Buscar configuração SMTP ativa
      const configRaw = await ctx.runQuery(
        internal.email.getActiveEmailConfig,
        {}
      );

      if (!configRaw) {
        console.error(
          "❌ Configuração SMTP não encontrada ou inativa para email:",
          email.destinatario
        );
        return {
          sucesso: false,
          erro: "Configuração de email não encontrada ou inativa. Verifique as configurações SMTP no painel de TI.",
        };
      }

      console.log("📧 Tentando enviar email:", {
        para: email.destinatario,
        assunto: email.assunto,
        servidor: configRaw.servidor,
        porta: configRaw.porta,
      });

      // Descriptografar senha usando função compatível com Node.js
      let senhaDescriptografada: string;
      try {
        senhaDescriptografada = await decryptSMTPPasswordNode(
          configRaw.senhaHash
        );
      } catch (decryptError) {
        const decryptErrorMessage =
          decryptError instanceof Error
            ? decryptError.message
            : String(decryptError);
        console.error(
          "Erro ao descriptografar senha SMTP:",
          decryptErrorMessage
        );
        return {
          sucesso: false,
          erro: `Erro ao descriptografar senha SMTP: ${decryptErrorMessage}`,
        };
      }

      const config = {
        ...configRaw,
        senha: senhaDescriptografada,
      };

      // Config já foi validado acima

      // Avisar mas não bloquear se não foi testado
      if (!config.testadoEm) {
        console.warn(
          "⚠️ Configuração SMTP não foi testada. Tentando enviar mesmo assim..."
        );
      }

      // Marcar como enviando
      await ctx.runMutation(internal.email.markEmailEnviando, {
        emailId: args.emailId,
      });

      // Criar transporter do nodemailer com configuração melhorada
      const transporterOptions: {
        host: string;
        port: number;
        secure: boolean;
        requireTLS?: boolean;
        auth: {
          user: string;
          pass: string;
        };
        tls?: {
          rejectUnauthorized: boolean;
          ciphers?: string;
        };
        connectionTimeout: number;
        greetingTimeout: number;
        socketTimeout: number;
        pool?: boolean;
        maxConnections?: number;
        maxMessages?: number;
      } = {
        host: config.servidor,
        port: config.porta,
        secure: config.usarSSL,
        auth: {
          user: config.usuario,
          pass: config.senha, // Senha já descriptografada
        },
        connectionTimeout: 15000, // 15 segundos
        greetingTimeout: 15000,
        socketTimeout: 15000,
        pool: true, // Usar pool de conexões
        maxConnections: 5,
        maxMessages: 100,
      };

      // Adicionar TLS apenas se necessário
      if (config.usarTLS) {
        transporterOptions.requireTLS = true;
        transporterOptions.tls = {
          rejectUnauthorized: false, // Permitir certificados autoassinados
        };
      } else if (config.usarSSL) {
        transporterOptions.tls = {
          rejectUnauthorized: false,
        };
      }

      const transporter = nodemailer.createTransport(transporterOptions);

      // Verificar conexão antes de enviar
      try {
        await transporter.verify();
        console.log("✅ Conexão SMTP verificada com sucesso");
      } catch (verifyError) {
        const verifyErrorMessage =
          verifyError instanceof Error
            ? verifyError.message
            : String(verifyError);
        console.warn(
          "⚠️ Falha na verificação SMTP, mas tentando enviar mesmo assim:",
          verifyErrorMessage
        );
        // Não bloquear envio por falha na verificação, apenas avisar
      }

      // Validar email destinatário antes de enviar
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (!emailRegex.test(email.destinatario)) {
        throw new Error(`Email destinatário inválido: ${email.destinatario}`);
      }

      // Criar versão texto do HTML (remover tags e decodificar entidades básicas)
      const textoPlano = email.corpo
        .replace(/<[^>]*>/g, "") // Remover tags HTML
        .replace(/&nbsp;/g, " ")
        .replace(/&amp;/g, "&")
        .replace(/&lt;/g, "<")
        .replace(/&gt;/g, ">")
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .trim();

      // Enviar email
      const info = await transporter.sendMail({
        from: `"${config.nomeRemetente}" <${config.emailRemetente}>`,
        to: email.destinatario,
        subject: email.assunto,
        html: email.corpo,
        text: textoPlano || email.assunto, // Versão texto para clientes que não suportam HTML
        headers: {
          "X-Mailer": "SGSE-Sistema-de-Gerenciamento-de-Secretaria",
          "X-Priority": "3",
        },
      });

      interface MessageInfo {
        messageId?: string;
        response?: string;
      }

      const messageInfo = info as MessageInfo;

      console.log("✅ Email enviado com sucesso!", {
        para: email.destinatario,
        assunto: email.assunto,
        messageId: messageInfo.messageId,
        response: messageInfo.response,
      });

      // Marcar como enviado
      await ctx.runMutation(internal.email.markEmailEnviado, {
        emailId: args.emailId,
      });

      return { sucesso: true };
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      const errorStack = error instanceof Error ? error.stack : undefined;

      console.error("❌ Erro ao enviar email:", {
        emailId: args.emailId,
        destinatario: email?.destinatario,
        erro: errorMessage,
        stack: errorStack,
      });

      // Marcar como falha com detalhes completos
      const erroCompleto = errorStack
        ? `${errorMessage}\n\nStack: ${errorStack}`
        : errorMessage;

      await ctx.runMutation(internal.email.markEmailFalha, {
        emailId: args.emailId,
        erro: erroCompleto.substring(0, 2000), // Limitar tamanho do erro
      });

      return { sucesso: false, erro: errorMessage };
    }
  },
});
