use crate::types::MailServerConfig;
use std::error::Error;
use trust_dns_resolver::proto::rr::RecordType;
use trust_dns_resolver::{
    config::{ResolverConfig, ResolverOpts},
    TokioAsyncResolver,
};

fn known_provider_config(domain: &str) -> Option<MailServerConfig> {
    match domain {
        "gmx.net" | "gmx.com" | "gmx.de" | "gmx.at" | "gmx.ch" => Some(MailServerConfig {
            imap_host: format!("imap.{}", domain),
            imap_port: 993,
            smtp_host: format!("mail.{}", domain),
            smtp_port: 587,
        }),
        "gmail.com" | "googlemail.com" => Some(MailServerConfig {
            imap_host: "imap.gmail.com".to_string(),
            imap_port: 993,
            smtp_host: "smtp.gmail.com".to_string(),
            smtp_port: 587,
        }),
        "yahoo.com" | "ymail.com" | "yahoo.co.uk" | "yahoo.co.in" => Some(MailServerConfig {
            imap_host: "imap.mail.yahoo.com".to_string(),
            imap_port: 993,
            smtp_host: "smtp.mail.yahoo.com".to_string(),
            smtp_port: 587,
        }),
        "outlook.com" | "hotmail.com" | "live.com" | "msn.com" => Some(MailServerConfig {
            imap_host: "outlook.office365.com".to_string(),
            imap_port: 993,
            smtp_host: "smtp.office365.com".to_string(),
            smtp_port: 587,
        }),
        "icloud.com" | "me.com" | "mac.com" => Some(MailServerConfig {
            imap_host: "imap.mail.me.com".to_string(),
            imap_port: 993,
            smtp_host: "smtp.mail.me.com".to_string(),
            smtp_port: 587,
        }),
        _ => None,
    }
}

pub async fn discover_mail_server(email: &str) -> Result<MailServerConfig, Box<dyn Error>> {
    let domain = email.split('@').nth(1).ok_or("Invalid email")?;

    // Check well-known providers first to avoid slow DNS fallbacks
    if let Some(config) = known_provider_config(domain) {
        return Ok(config);
    }

    // Create async resolver
    // Note: TokioAsyncResolver::tokio constructor is used for tokio runtime
    let resolver = TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());

    // Try IMAPS SRV (_imaps._tcp.domain.com)
    let imap_srv = format!("_imaps._tcp.{}", domain);
    let imap_config = match resolver.lookup(&imap_srv, RecordType::SRV).await {
        Ok(response) => {
            let srv = response.iter().next().ok_or("No SRV records")?;
            if let Some(srv_data) = srv.as_srv() {
                (
                    srv_data
                        .target()
                        .to_string()
                        .trim_end_matches('.')
                        .to_string(),
                    srv_data.port(),
                )
            } else {
                (domain.to_string(), 993) // Fallback
            }
        }
        Err(_) => {
            // No SRV, use standard port
            (domain.to_string(), 993)
        }
    };

    // Try SMTP Submission SRV (_submission._tcp.domain.com)
    let smtp_srv = format!("_submission._tcp.{}", domain);
    let smtp_config = match resolver.lookup(&smtp_srv, RecordType::SRV).await {
        Ok(response) => {
            let srv = response.iter().next().ok_or("No SRV records")?;
            if let Some(srv_data) = srv.as_srv() {
                (
                    srv_data
                        .target()
                        .to_string()
                        .trim_end_matches('.')
                        .to_string(),
                    srv_data.port(),
                )
            } else {
                (domain.to_string(), 587) // Fallback
            }
        }
        Err(_) => (domain.to_string(), 587),
    };

    Ok(MailServerConfig {
        imap_host: imap_config.0,
        imap_port: imap_config.1,
        smtp_host: smtp_config.0,
        smtp_port: smtp_config.1,
    })
}
