// pkg/email/email.go
package email

import (
	"bytes"
	"fmt"
	"html/template"
	"time"

	"api_bb/internal/config"
	"api_bb/pkg/logger"

	"github.com/wneessen/go-mail"
	"go.uber.org/zap"
)

// Service представляет сервис для отправки email
type Service struct {
	client   *mail.Client
	config   *config.Config
	logger   *zap.Logger
	tmpl     *template.Template
	fromAddr string
	isActive bool
}

// NewService создает новый экземпляр email сервиса
func NewService(cfg *config.Config) (*Service, error) {
	log := logger.Get()
	log.Info("Initializing email service")

	// Проверяем обязательные параметры конфигурации
	if err := validateConfig(cfg); err != nil {
		log.Warn("Email service configuration is invalid, service will be disabled", zap.Error(err))
		return &Service{
			logger:   log,
			isActive: false,
		}, nil
	}

	// Создаем SMTP клиент с правильными настройками
	client, err := createSMTPClient(cfg)
	if err != nil {
		log.Warn("Failed to create SMTP client, email service will be disabled", zap.Error(err))
		return &Service{
			logger:   log,
			isActive: false,
		}, nil
	}

	// Загружаем шаблоны писем
	tmpl, err := loadTemplates()
	if err != nil {
		log.Warn("Failed to load email templates, email service will be disabled", zap.Error(err))
		return &Service{
			logger:   log,
			isActive: false,
		}, nil
	}

	service := &Service{
		client:   client,
		config:   cfg,
		logger:   log,
		tmpl:     tmpl,
		fromAddr: cfg.FromEmail,
		isActive: true,
	}

	log.Info("Email service initialized successfully",
		zap.String("host", cfg.SMTPHost),
		zap.Int("port", cfg.SMTPPort),
		zap.String("from", cfg.FromEmail))

	return service, nil
}

// validateConfig проверяет корректность конфигурации email
func validateConfig(cfg *config.Config) error {
	if cfg.SMTPHost == "" {
		return fmt.Errorf("SMTP host is required")
	}

	if cfg.SMTPPort <= 0 || cfg.SMTPPort > 65535 {
		return fmt.Errorf("invalid SMTP port: %d", cfg.SMTPPort)
	}

	if cfg.SMTPUsername == "" {
		return fmt.Errorf("SMTP username is required")
	}

	if cfg.SMTPPassword == "" {
		return fmt.Errorf("SMTP password is required")
	}

	if cfg.FromEmail == "" {
		return fmt.Errorf("from email is required")
	}

	if cfg.FrontendURL == "" {
		return fmt.Errorf("frontend URL is required")
	}

	return nil
}

// createSMTPClient создает SMTP клиент с правильными настройками
func createSMTPClient(cfg *config.Config) (*mail.Client, error) {
	opts := []mail.Option{
		mail.WithPort(cfg.SMTPPort),
		mail.WithSMTPAuth(mail.SMTPAuthPlain),
		mail.WithUsername(cfg.SMTPUsername),
		mail.WithPassword(cfg.SMTPPassword),
	}

	// Настраиваем TLS в зависимости от порта
	switch cfg.SMTPPort {
	case 587:
		// STARTTLS для порта 587
		opts = append(opts, mail.WithTLSPolicy(mail.TLSMandatory))
	case 465:
		// SSL/TLS для порта 465
		opts = append(opts, mail.WithSSL())
	default:
		// Opportunistic TLS для других портов
		opts = append(opts, mail.WithTLSPolicy(mail.TLSOpportunistic))
	}

	return mail.NewClient(cfg.SMTPHost, opts...)
}

// loadTemplates загружает HTML шаблоны для писем
func loadTemplates() (*template.Template, error) {
	tmpl := template.New("email")

	templates := map[string]string{
		"verification":   verificationTemplate,
		"password_reset": passwordResetTemplate,
		"newsletter":     newsletterTemplate,
	}

	for name, content := range templates {
		var err error
		tmpl, err = tmpl.New(name).Parse(content)
		if err != nil {
			return nil, fmt.Errorf("failed to parse template %s: %w", name, err)
		}
	}

	return tmpl, nil
}

// IsActive возвращает статус сервиса
func (s *Service) IsActive() bool {
	return s.isActive
}

// EmailData содержит данные для шаблонов писем
type EmailData struct {
	UserName    string
	AppName     string
	FrontendURL string
	Token       string
	Subject     string
	Content     string
	Year        int
}

// SendVerificationEmail отправляет email для подтверждения адреса
func (s *Service) SendVerificationEmail(to, userName, token string) error {
	if !s.isActive {
		s.logger.Warn("Email service is disabled, skipping verification email",
			zap.String("to", to), zap.String("user", userName))
		return nil
	}

	s.logger.Info("Sending verification email", zap.String("to", to), zap.String("user", userName))

	data := EmailData{
		UserName:    userName,
		AppName:     "Бегущий Башкир",
		FrontendURL: s.config.FrontendURL,
		Token:       token,
		Subject:     "Подтверждение email",
		Year:        time.Now().Year(),
	}

	return s.sendEmail(to, "Подтверждение email - Бегущий Башкир", "verification", data)
}

// SendPasswordResetEmail отправляет email для сброса пароля
func (s *Service) SendPasswordResetEmail(to, userName, token string) error {
	if !s.isActive {
		s.logger.Warn("Email service is disabled, skipping password reset email",
			zap.String("to", to), zap.String("user", userName))
		return nil
	}

	s.logger.Info("Sending password reset email", zap.String("to", to), zap.String("user", userName))

	data := EmailData{
		UserName:    userName,
		AppName:     "Бегущий Башкир",
		FrontendURL: s.config.FrontendURL,
		Token:       token,
		Subject:     "Восстановление пароля",
		Year:        time.Now().Year(),
	}

	return s.sendEmail(to, "Восстановление пароля - Бегущий Башкир", "password_reset", data)
}

// SendNewsletterEmail отправляет email рассылку
func (s *Service) SendNewsletterEmail(to, userName, subject, content string) error {
	if !s.isActive {
		s.logger.Warn("Email service is disabled, skipping newsletter",
			zap.String("to", to), zap.String("user", userName), zap.String("subject", subject))
		return nil
	}

	s.logger.Info("Sending newsletter email",
		zap.String("to", to),
		zap.String("user", userName),
		zap.String("subject", subject))

	data := EmailData{
		UserName:    userName,
		AppName:     "Бегущий Башкир",
		FrontendURL: s.config.FrontendURL,
		Subject:     subject,
		Content:     content,
		Year:        time.Now().Year(),
	}

	// Для новостей используем специальный шаблон
	var body bytes.Buffer
	if err := s.tmpl.ExecuteTemplate(&body, "newsletter", data); err != nil {
		s.logger.Error("Failed to execute newsletter template", zap.Error(err))
		return fmt.Errorf("failed to execute newsletter template: %w", err)
	}

	msg := mail.NewMsg()
	if err := msg.From(s.fromAddr); err != nil {
		return fmt.Errorf("failed to set from address: %w", err)
	}
	if err := msg.To(to); err != nil {
		return fmt.Errorf("failed to set to address: %w", err)
	}

	msg.Subject(subject)
	msg.SetBodyString(mail.TypeTextHTML, body.String())

	if err := s.client.DialAndSend(msg); err != nil {
		s.logger.Error("Failed to send newsletter email", zap.Error(err))
		return fmt.Errorf("failed to send newsletter email: %w", err)
	}

	s.logger.Info("Newsletter email sent successfully", zap.String("to", to))
	return nil
}

// sendEmail общий метод для отправки email
func (s *Service) sendEmail(to, subject, templateName string, data EmailData) error {
	var body bytes.Buffer
	if err := s.tmpl.ExecuteTemplate(&body, templateName, data); err != nil {
		s.logger.Error("Failed to execute email template",
			zap.String("template", templateName),
			zap.Error(err))
		return fmt.Errorf("failed to execute template %s: %w", templateName, err)
	}

	msg := mail.NewMsg()
	if err := msg.From(s.fromAddr); err != nil {
		return fmt.Errorf("failed to set from address: %w", err)
	}
	if err := msg.To(to); err != nil {
		return fmt.Errorf("failed to set to address: %w", err)
	}

	msg.Subject(subject)
	msg.SetBodyString(mail.TypeTextHTML, body.String())

	if err := s.client.DialAndSend(msg); err != nil {
		s.logger.Error("Failed to send email",
			zap.String("type", templateName),
			zap.String("to", to),
			zap.Error(err))
		return fmt.Errorf("failed to send email: %w", err)
	}

	s.logger.Info("Email sent successfully",
		zap.String("type", templateName),
		zap.String("to", to))
	return nil
}

// TestConnection тестирует подключение к SMTP серверу
func (s *Service) TestConnection() error {
	if !s.isActive {
		return fmt.Errorf("email service is disabled")
	}

	// Создаем тестовое сообщение
	msg := mail.NewMsg()
	if err := msg.From(s.fromAddr); err != nil {
		return fmt.Errorf("failed to set from address: %w", err)
	}
	if err := msg.To(s.fromAddr); err != nil {
		return fmt.Errorf("failed to set to address: %w", err)
	}

	msg.Subject("Тестовое письмо - Бегущий Башкир")
	msg.SetBodyString(mail.TypeTextPlain, "Это тестовое письмо для проверки подключения.")

	// Пытаемся отправить тестовое письмо
	if err := s.client.DialAndSend(msg); err != nil {
		return fmt.Errorf("failed to send test email: %w", err)
	}

	s.logger.Info("SMTP connection test successful")
	return nil
}

// Шаблоны писем остаются без изменений...
const verificationTemplate = `
{{define "verification"}}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background: linear-gradient(135deg, #2e8b57, #3cb371); color: white; padding: 2rem; text-align: center; border-radius: 10px 10px 0 0; }
        .content { padding: 2rem; background: #f8f9fa; }
        .footer { padding: 1rem; text-align: center; color: #666; font-size: 0.9rem; }
        .cta-button { display: inline-block; padding: 12px 24px; background: #2e8b57; color: white; text-decoration: none; border-radius: 5px; margin: 1rem 0; }
        .token { background: #e9ecef; padding: 10px; border-radius: 5px; font-family: monospace; margin: 1rem 0; }
    </style>
</head>
<body>
    <div class="header">
        <h1>🏃 Бегущий Башкир</h1>
        <p>Подтверждение email адреса</p>
    </div>
    <div class="content">
        <h2>Привет, {{.UserName}}!</h2>
        <p>Благодарим за регистрацию в приложении "Бегущий Башкир". Для завершения регистрации подтвердите ваш email адрес.</p>
        
        <a href="{{.FrontendURL}}/verify-email?token={{.Token}}" class="cta-button">
            Подтвердить Email
        </a>
        
        <p>Или скопируйте эту ссылку в браузер:</p>
        <div class="token">{{.FrontendURL}}/verify-email?token={{.Token}}</div>
        
        <p>Ссылка действительна в течение 24 часов.</p>
    </div>
    <div class="footer">
        <p>© {{.Year}} Бегущий Башкир. Все права защищены.</p>
    </div>
</body>
</html>
{{end}}
`

const passwordResetTemplate = `
{{define "password_reset"}}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background: linear-gradient(135deg, #dc3545, #e35d6a); color: white; padding: 2rem; text-align: center; border-radius: 10px 10px 0 0; }
        .content { padding: 2rem; background: #f8f9fa; }
        .footer { padding: 1rem; text-align: center; color: #666; font-size: 0.9rem; }
        .cta-button { display: inline-block; padding: 12px 24px; background: #dc3545; color: white; text-decoration: none; border-radius: 5px; margin: 1rem 0; }
        .token { background: #e9ecef; padding: 10px; border-radius: 5px; font-family: monospace; margin: 1rem 0; }
    </style>
</head>
<body>
    <div class="header">
        <h1>🏃 Бегущий Башкир</h1>
        <p>Восстановление пароля</p>
    </div>
    <div class="content">
        <h2>Привет, {{.UserName}}!</h2>
        <p>Мы получили запрос на восстановление пароля для вашего аккаунта.</p>
        
        <a href="{{.FrontendURL}}/reset-password?token={{.Token}}" class="cta-button">
            Восстановить пароль
        </a>
        
        <p>Или скопируйте эту ссылку в браузер:</p>
        <div class="token">{{.FrontendURL}}/reset-password?token={{.Token}}</div>
        
        <p>Если вы не запрашивали восстановление пароля, просто проигнорируйте это письмо.</p>
        <p>Ссылка действительна в течение 1 часа.</p>
    </div>
    <div class="footer">
        <p>© {{.Year}} Бегущий Башкир. Все права защищены.</p>
    </div>
</body>
</html>
{{end}}
`

const newsletterTemplate = `
{{define "newsletter"}}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background: linear-gradient(135deg, #2e8b57, #3cb371); color: white; padding: 2rem; text-align: center; border-radius: 10px 10px 0 0; }
        .content { padding: 2rem; background: #f8f9fa; }
        .footer { padding: 1rem; text-align: center; color: #666; font-size: 0.9rem; }
        .newsletter-content { line-height: 1.8; }
        .cta-button { display: inline-block; padding: 12px 24px; background: #2e8b57; color: white; text-decoration: none; border-radius: 5px; margin: 1rem 0; }
    </style>
</head>
<body>
    <div class="header">
        <h1>🏃 Бегущий Башкир</h1>
        <p>Новости и обновления</p>
    </div>
    <div class="content">
        <h2>Привет, {{.UserName}}!</h2>
        <div class="newsletter-content">
            {{.Content}}
        </div>
    </div>
    <div class="footer">
        <p>© {{.Year}} Бегущий Башкир. Все права защищены.</p>
        <p><a href="{{.FrontendURL}}/unsubscribe" style="color: #666;">Отписаться от рассылки</a></p>
    </div>
</body>
</html>
{{end}}
`
