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(())

    }

    pub async fn send_contact_email(&self, contact: crate::models::ContactEmail) -> Result<()> {
        let phone_str = contact.phone.as_deref().unwrap_or("Not provided");
        
        let subject_html = if let Some(ref subject) = contact.subject {
            format!("<p><strong>Subject:</strong> {}</p>\n", subject)
        } else {
            String::new()
        };

        let html_body = format!(
            "<h2>New Contact Form Submission</h2>\n\
            <p><strong>Name:</strong> {} {}</p>\n\
            <p><strong>Email:</strong> {}</p>\n\
            <p><strong>Phone:</strong> {}</p>\n\
            {}\
            <h3>Message:</h3>\n\
            <p>{}</p>\n",
            contact.first_name,
            contact.last_name,
            contact.email,
            phone_str,
            subject_html,
            contact.message.replace('\n', "<br>")
        );

        let default_subject = format!("New Contact Form Submission from {} {}", 
            contact.first_name, contact.last_name);
        let subject = contact.subject.as_deref().unwrap_or(&default_subject);

        let email = Message::builder()
            .from(self.config.from_email.parse()?)
            .to(self.config.admin_email.parse()?)
            .subject(subject)
            .header(lettre::message::header::ContentType::TEXT_HTML)
            .body(html_body)?;

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

// Error conversions
impl From<lettre::error::Error> for crate::error::ApiError {
    fn from(error: lettre::error::Error) -> Self {
        crate::error::ApiError::ValidationError(format!("Email error: {}", error))
    }
}

impl From<lettre::address::AddressError> for crate::error::ApiError {
    fn from(error: lettre::address::AddressError) -> Self {
        crate::error::ApiError::ValidationError(format!("Email address error: {}", error))
    }
}

impl From<lettre::transport::smtp::Error> for crate::error::ApiError {
    fn from(error: lettre::transport::smtp::Error) -> Self {
        crate::error::ApiError::ValidationError(format!("SMTP error: {}", error))
    }
}
