package config

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/valyala/bytebufferpool"
	mail "github.com/xhit/go-simple-mail/v2"
)

type Mail struct {
	*mail.SMTPServer
	*mail.SMTPClient
	Host        string `mapstructure:"MAIL_HOST" yaml:"host" env:"MAIL_HOST" env-default:"smtp-mail.outlook.com"`
	Username    string `mapstructure:"MAIL_USERNAME" yaml:"username" env:"MAIL_USERNAME" env-default:"info@u-site.app"`
	Password    string `mapstructure:"MAIL_PASSWORD" yaml:"password" env:"MAIL_PASSWORD" env-default:""`
	Encryption  string `mapstructure:"MAIL_ENCRYPTION" yaml:"encryption" env:"MAIL_ENCRYPTION" env-default:"tls"`
	FromAddress string `mapstructure:"MAIL_FROM_ADDRESS" yaml:"from_address" env:"MAIL_FROM_ADDRESS" env-default:"info@u-site.app"`
	FromName    string `mapstructure:"MAIL_FROM_NAME" yaml:"from_name" env:"MAIL_FROM_NAME" env-default:"Usite SAS BIC"`
	View        *ViewConfig
	Port        int `mapstructure:"MAIL_PORT" yaml:"port" env:"MAIL_PORT" env-default:"587"` // Cambié a 465 para SSL
}

// Enviar correo
func (m *Mail) Send(to string, subject string, body string, ccEmails ...string) error {
	// Configurar el cliente SMTP antes de enviar cada correo
	if m.SMTPServer == nil {
		m.SetupMailer()
	}

	// Usar el remitente de la config activa; si está vacío, caer al env
	from := m.FromAddress
	if from == "" {
		from = os.Getenv("MAIL_FROM_ADDRESS")
	}
	if from == "" {
		log.Println("Error: FromAddress no está configurado")
		return fmt.Errorf("MAIL_FROM_ADDRESS no está configurado")
	}

	// Construir el campo From con nombre si está disponible: "Nombre <email>"
	fromName := m.FromName
	if fromName == "" {
		fromName = os.Getenv("MAIL_FROM_NAME")
	}
	fromHeader := from
	// Solo usar "Nombre <email>" si el nombre no es una dirección de email ni igual al from
	if fromName != "" && fromName != from && !strings.Contains(fromName, "@") {
		fromHeader = fmt.Sprintf("%s <%s>", fromName, from)
	}

	// Crear nuevo mensaje de correo
	email := mail.NewMSG()
	email.SetFrom(fromHeader).
		AddTo(to).
		SetSubject(subject).
		SetBody(mail.TextHTML, body)

	// Crear un nuevo cliente SMTP
	client, err := m.SMTPServer.Connect()
	if err != nil {
		log.Printf("Error conectando al servidor SMTP: %s", err)
		return err
	}

	// Enviar el correo usando el cliente SMTP nuevo
	err = email.Send(client)
	if err != nil {
		log.Printf("Error enviando el correo: %s", err)
		return err
	}

	log.Println("Correo enviado con éxito")
	return nil
}

// Preparar HTML para el cuerpo del correo
func (m *Mail) PrepareHtml(view string, body fiber.Map) string {
	buf := bytebufferpool.Get()
	defer bytebufferpool.Put(buf)
	// app.Settings.Views.Render (asegúrate de que el motor de plantillas esté configurado)
	if err := m.View.Template.TemplateEngine.Render(buf, view, body, "layouts/email"); err != nil {
		log.Printf("Error rendering HTML: %s", err)
	}
	return buf.String()
}

// Configuración inicial del cliente SMTP
func (m *Mail) SetupMailer() {
	var err error
	m.SMTPServer = mail.NewSMTPClient()
	m.SMTPServer.Host = m.Host
	m.SMTPServer.Port = m.Port
	m.SMTPServer.Username = m.Username
	m.SMTPServer.Password = m.Password
	switch strings.ToLower(strings.ReplaceAll(m.Encryption, "/", "")) {
	case "ssl", "ssltls":
		m.SMTPServer.Encryption = mail.EncryptionSSL
	case "tls", "starttls":
		m.SMTPServer.Encryption = mail.EncryptionSTARTTLS
	default:
		m.SMTPServer.Encryption = mail.EncryptionNone
	}

	// Configuración de tiempo y conexión
	m.SMTPServer.KeepAlive = false
	m.SMTPServer.ConnectTimeout = 10 * time.Second
	m.SMTPServer.SendTimeout = 10 * time.Second

	// Conectar al servidor SMTP
	m.SMTPClient, err = m.SMTPServer.Connect()
	if err != nil {
		log.Printf("Error conectando al servidor SMTP: %s", err)
	}
}
