use lettre::{
    transport::smtp::authentication::Credentials,
    AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor,
};
use std::env;

use crate::{error::Result, models::PendingEvent};

#[derive(Clone)]
pub struct EmailConfig {
    pub smtp_host: String,
    pub smtp_port: u16,
    pub smtp_user: String,
    pub smtp_pass: String,
    pub from_email: String,
    pub admin_email: String,
}

impl EmailConfig {
    pub fn from_env() -> Result<Self> {
        Ok(EmailConfig {
            smtp_host: env::var("SMTP_HOST").expect("SMTP_HOST not set"),
            smtp_port: env::var("SMTP_PORT")
                .unwrap_or_else(|_| "587".to_string())
                .parse()
                .expect("Invalid SMTP_PORT"),
            smtp_user: env::var("SMTP_USER").expect("SMTP_USER not set"),
            smtp_pass: env::var("SMTP_PASS").expect("SMTP_PASS not set"),
            from_email: env::var("SMTP_FROM").expect("SMTP_FROM not set"),
            admin_email: env::var("ADMIN_EMAIL").expect("ADMIN_EMAIL not set"),
        })
    }
}

pub struct Mailer {
    transport: AsyncSmtpTransport<Tokio1Executor>,
    config: EmailConfig,
}

impl Mailer {
    pub fn new(config: EmailConfig) -> Result<Self> {
        let creds = Credentials::new(config.smtp_user.clone(), config.smtp_pass.clone());

        let transport = AsyncSmtpTransport::<Tokio1Executor>::starttls_relay(&config.smtp_host)?
            .port(config.smtp_port)
            .credentials(creds)
            .build();

        Ok(Mailer { transport, config })
    }

    pub async fn send_event_submission_notification(&self, event: &PendingEvent) -> Result<()> {
        let email = Message::builder()
            .from(self.config.from_email.parse()?)
            .to(self.config.admin_email.parse()?)
            .subject(&format!("New Event Submission: {}", event.title))
            .body(format!(
                "New event submitted for approval:\n\nTitle: {}\nDescription: {}\nStart: {}\nLocation: {}\nSubmitted by: {}",
                event.title,
                event.description,
                event.start_time,
                event.location,
                event.submitter_email.as_deref().unwrap_or("Unknown")
            ))?;

        self.transport.send(email).await?;
        tracing::info!("Event submission email sent successfully");
        Ok(())
    }

    pub async fn send_event_approval_notification(&self, event: &PendingEvent, _admin_notes: Option<&str>) -> Result<()> {
        if let Some(submitter_email) = &event.submitter_email {
            let email = Message::builder()
                .from(self.config.from_email.parse()?)
                .to(submitter_email.parse()?)
                .subject(&format!("Event Approved: {}", event.title))
                .body(format!(
                    "Great news! Your event '{}' has been approved and will be published.",
                    event.title
                ))?;

            self.transport.send(email).await?;
        }
        Ok(())
    }

    pub async fn send_event_rejection_notification(&self, event: &PendingEvent, admin_notes: Option<&str>) -> Result<()> {
        if let Some(submitter_email) = &event.submitter_email {
            let email = Message::builder()
                .from(self.config.from_email.parse()?)
                .to(submitter_email.parse()?)
                .subject(&format!("Event Update: {}", event.title))
                .body(format!(
                    "Thank you for submitting '{}'. After review, we're unable to include this event at this time.\n\n{}",
                    event.title,
                    admin_notes.unwrap_or("Please feel free to submit future events.")
                ))?;

            self.transport.send(email).await?;
        }
        Ok(())

