use axum::{
    extract::{Json, Path, State},
    http::StatusCode,
    response::IntoResponse,
    routing::{get, post},
    Router,
};
use serde::{Deserialize, Serialize};

use crate::AppState;

pub fn router() -> Router<AppState> {
    Router::new()
        .route("/templates", get(list_templates))
        .route("/templates/{name}/preview", get(preview_template))
        .route("/templates/{name}/test", post(send_test_email))
        .route("/email-config", get(get_email_config).post(update_email_config))
        .route("/email-test", post(test_email_connection))
}

#[derive(Serialize)]
struct TemplateInfo {
    name: String,
    subject: String,
    category: String,
    description: String,
}

#[derive(Serialize)]
struct TemplateListResponse {
    templates: Vec<TemplateInfo>,
}

async fn list_templates() -> impl IntoResponse {
    let templates = vec![
        TemplateInfo {
            name: "welcome".to_string(),
            subject: "Welcome to Nxtgauge!".to_string(),
            category: "Auth & Account".to_string(),
            description: "Sent when user registers successfully".to_string(),
        },
        TemplateInfo {
            name: "verify-email".to_string(),
            subject: "Verify Your Email Address".to_string(),
            category: "Auth & Account".to_string(),
            description: "OTP verification email".to_string(),
        },
        TemplateInfo {
            name: "password-reset".to_string(),
            subject: "Reset Your Password".to_string(),
            category: "Auth & Account".to_string(),
            description: "Password reset link".to_string(),
        },
        TemplateInfo {
            name: "password-changed".to_string(),
            subject: "Password Changed Successfully".to_string(),
            category: "Auth & Account".to_string(),
            description: "Confirmation after password change".to_string(),
        },
        TemplateInfo {
            name: "account-suspended".to_string(),
            subject: "Account Suspended".to_string(),
            category: "Auth & Account".to_string(),
            description: "Account suspension notice".to_string(),
        },
        TemplateInfo {
            name: "new-device-login".to_string(),
            subject: "New Login Detected".to_string(),
            category: "Auth & Account".to_string(),
            description: "Suspicious login alert".to_string(),
        },
        TemplateInfo {
            name: "onboarding-submitted".to_string(),
            subject: "Profile Submitted for Review".to_string(),
            category: "Onboarding".to_string(),
            description: "Profile submitted confirmation".to_string(),
        },
        TemplateInfo {
            name: "profile-verified".to_string(),
            subject: "Your Profile is Verified!".to_string(),
            category: "Onboarding".to_string(),
            description: "Profile approval confirmation".to_string(),
        },
        TemplateInfo {
            name: "profile-rejected".to_string(),
            subject: "Profile Verification Update".to_string(),
            category: "Onboarding".to_string(),
            description: "Profile rejection with reason".to_string(),
        },
        TemplateInfo {
            name: "documents-requested".to_string(),
            subject: "Additional Documents Required".to_string(),
            category: "Onboarding".to_string(),
            description: "Request for additional documents".to_string(),
        },
        TemplateInfo {
            name: "job-pending".to_string(),
            subject: "Job Posted Successfully".to_string(),
            category: "Jobs".to_string(),
            description: "Job submitted for approval".to_string(),
        },
        TemplateInfo {
            name: "job-approved".to_string(),
            subject: "Your Job is Now Live!".to_string(),
            category: "Jobs".to_string(),
            description: "Job approval confirmation".to_string(),
        },
        TemplateInfo {
            name: "job-rejected".to_string(),
            subject: "Job Posting Needs Updates".to_string(),
            category: "Jobs".to_string(),
            description: "Job rejection with reason".to_string(),
        },
        TemplateInfo {
            name: "job-expired".to_string(),
            subject: "Job Posting Expired".to_string(),
            category: "Jobs".to_string(),
            description: "Job posting expiry notice".to_string(),
        },
        TemplateInfo {
            name: "application-received".to_string(),
            subject: "New Application Received".to_string(),
            category: "Applications".to_string(),
            description: "New candidate application".to_string(),
        },
        TemplateInfo {
            name: "application-status".to_string(),
            subject: "Application Status Update".to_string(),
            category: "Applications".to_string(),
            description: "Application status changed".to_string(),
        },
        TemplateInfo {
            name: "requirement-pending".to_string(),
            subject: "Requirement Submitted Successfully".to_string(),
            category: "Requirements".to_string(),
            description: "Requirement submitted for approval".to_string(),
        },
        TemplateInfo {
            name: "requirement-approved".to_string(),
            subject: "Your Requirement is Now Live!".to_string(),
            category: "Requirements".to_string(),
            description: "Requirement approval confirmation".to_string(),
        },
        TemplateInfo {
            name: "requirement-expired".to_string(),
            subject: "Requirement Expired".to_string(),
            category: "Requirements".to_string(),
            description: "Requirement expiry notice".to_string(),
        },
        TemplateInfo {
            name: "new-lead-request".to_string(),
            subject: "New Request Received".to_string(),
            category: "Leads".to_string(),
            description: "Customer receives new lead request".to_string(),
        },
        TemplateInfo {
            name: "lead-request-sent".to_string(),
            subject: "Lead Request Sent".to_string(),
            category: "Leads".to_string(),
            description: "Professional confirmation of lead request".to_string(),
        },
        TemplateInfo {
            name: "lead-request-accepted".to_string(),
            subject: "Lead Request Accepted!".to_string(),
            category: "Leads".to_string(),
            description: "Professional's request was accepted".to_string(),
        },
        TemplateInfo {
            name: "lead-request-rejected".to_string(),
            subject: "Lead Request Update".to_string(),
            category: "Leads".to_string(),
            description: "Professional's request was rejected".to_string(),
        },
        TemplateInfo {
            name: "lead-expired".to_string(),
            subject: "Lead Request Expired".to_string(),
            category: "Leads".to_string(),
            description: "Lead request expired (coins returned)".to_string(),
        },
        TemplateInfo {
            name: "new-matched-lead".to_string(),
            subject: "New Lead Available!".to_string(),
            category: "Leads".to_string(),
            description: "New requirement matching expertise".to_string(),
        },
        TemplateInfo {
            name: "payment-success".to_string(),
            subject: "Payment Successful!".to_string(),
            category: "Payments".to_string(),
            description: "Tracecoin purchase confirmation".to_string(),
        },
        TemplateInfo {
            name: "invoice-generated".to_string(),
            subject: "Invoice Generated".to_string(),
            category: "Payments".to_string(),
            description: "Invoice ready for download".to_string(),
        },
        TemplateInfo {
            name: "manual-credit".to_string(),
            subject: "Tracecoins Credited to Your Account".to_string(),
            category: "Payments".to_string(),
            description: "Admin manual credit notification".to_string(),
        },
        TemplateInfo {
            name: "credit-usage".to_string(),
            subject: "Tracecoins Used".to_string(),
            category: "Payments".to_string(),
            description: "Credit usage confirmation".to_string(),
        },
        TemplateInfo {
            name: "low-credit-balance".to_string(),
            subject: "Low Tracecoin Balance".to_string(),
            category: "Payments".to_string(),
            description: "Low balance warning".to_string(),
        },
        TemplateInfo {
            name: "support-ticket-created".to_string(),
            subject: "Support Ticket Received".to_string(),
            category: "Support".to_string(),
            description: "Ticket creation confirmation".to_string(),
        },
        TemplateInfo {
            name: "support-ticket-replied".to_string(),
            subject: "New Response on Your Ticket".to_string(),
            category: "Support".to_string(),
            description: "Admin replied to ticket".to_string(),
        },
        TemplateInfo {
            name: "support-ticket-resolved".to_string(),
            subject: "Ticket Resolved".to_string(),
            category: "Support".to_string(),
            description: "Ticket resolution confirmation".to_string(),
        },
        TemplateInfo {
            name: "policy-update".to_string(),
            subject: "Important Policy Update".to_string(),
            category: "Policy".to_string(),
            description: "Terms/privacy policy update".to_string(),
        },
    ];

    (StatusCode::OK, Json(TemplateListResponse { templates }))
}

#[derive(Serialize)]
struct PreviewResponse {
    html: String,
    subject: String,
    variables: Vec<String>,
}

async fn preview_template(Path(name): Path<String>) -> impl IntoResponse {
    // Return sample preview with embedded template content
    // In production, this would render the actual template with sample data
    let subject = match name.as_str() {
        "welcome" => "Welcome to Nxtgauge!",
        "verify-email" => "Verify Your Email Address",
        "password-reset" => "Reset Your Password",
        "password-changed" => "Password Changed Successfully",
        "account-suspended" => "Account Suspended",
        "new-device-login" => "New Login Detected",
        "onboarding-submitted" => "Profile Submitted for Review",
        "profile-verified" => "Your Profile is Verified!",
        "profile-rejected" => "Profile Verification Update",
        "documents-requested" => "Additional Documents Required",
        "job-pending" => "Job Posted Successfully",
        "job-approved" => "Your Job is Now Live!",
        "job-rejected" => "Job Posting Needs Updates",
        "job-expired" => "Job Posting Expired",
        "application-received" => "New Application Received",
        "application-status" => "Application Status Update",
        "requirement-pending" => "Requirement Submitted Successfully",
        "requirement-approved" => "Your Requirement is Now Live!",
        "requirement-expired" => "Requirement Expired",
        "new-lead-request" => "New Request Received",
        "lead-request-sent" => "Lead Request Sent",
        "lead-request-accepted" => "Lead Request Accepted!",
        "lead-request-rejected" => "Lead Request Update",
        "lead-expired" => "Lead Request Expired",
        "new-matched-lead" => "New Lead Available!",
        "payment-success" => "Payment Successful!",
        "invoice-generated" => "Invoice Generated",
        "manual-credit" => "Tracecoins Credited to Your Account",
        "credit-usage" => "Tracecoins Used",
        "low-credit-balance" => "Low Tracecoin Balance",
        "support-ticket-created" => "Support Ticket Received",
        "support-ticket-replied" => "New Response on Your Ticket",
        "support-ticket-resolved" => "Ticket Resolved",
        "policy-update" => "Important Policy Update",
        _ => "Email Preview",
    };

    let sample_html = format!(
        r##"<!DOCTYPE html>
        <html>
        <head>
            <style>
                body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }}
                .email-wrapper {{ max-width: 600px; margin: 0 auto; background: white; }}
                .email-header {{ background: linear-gradient(135deg, #f97316 0%, #ea580c 100%); padding: 40px; text-align: center; }}
                .logo {{ color: white; font-size: 28px; font-weight: bold; }}
                .email-content {{ padding: 40px; color: #374151; }}
                .email-title {{ color: #111827; font-size: 24px; margin-bottom: 20px; }}
                .btn-cta {{ display: inline-block; background: linear-gradient(135deg, #f97316 0%, #ea580c 100%); color: white; padding: 14px 32px; border-radius: 8px; text-decoration: none; margin: 20px 0; }}
                .detail-card {{ background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 8px; padding: 20px; margin: 20px 0; }}
                .detail-row {{ display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #e5e7eb; }}
                .info-box {{ background: #fff7ed; border-left: 4px solid #f97316; padding: 20px; margin: 20px 0; }}
            </style>
        </head>
        <body>
            <div class="email-wrapper">
                <div class="email-header">
                    <div class="logo">NXT<span style="font-weight:300">GAUGE</span></div>
                </div>
                <div class="email-content">
                    <h1 class="email-title">{}</h1>
                    <p>Hi John,</p>
                    <p>This is a sample preview of the <strong>{}</strong> email template.</p>
                    
                    <div class="detail-card">
                        <div class="detail-row">
                            <span style="color: #6b7280;">Template</span>
                            <span style="font-weight: 600;">{}</span>
                        </div>
                        <div class="detail-row">
                            <span style="color: #6b7280;">Status</span>
                            <span style="color: #059669; font-weight: 600;">Active</span>
                        </div>
                    </div>
                    
                    <div class="info-box">
                        <p style="margin: 0; color: #9a3412;"><strong>Sample Data:</strong> This preview uses placeholder values.</p>
                    </div>
                    
                    <a href="#" class="btn-cta">Sample Action Button</a>
                    
                    <p>Best regards,<br><strong>The Nxtgauge Team</strong></p>
                </div>
            </div>
        </body>
        </html>"##,
        subject, name, name
    );

    let vars = match name.as_str() {
        "welcome" => vec!["first_name", "dashboard_url"],
        "verify-email" => vec!["first_name", "otp_code"],
        "password-reset" => vec!["first_name", "reset_url"],
        "password-changed" => vec!["first_name", "email", "changed_at", "security_url"],
        "account-suspended" => vec!["first_name", "suspension_reason"],
        "new-device-login" => vec!["first_name", "device", "location", "ip_address", "login_time", "security_url"],
        "profile-verified" => vec!["first_name", "role_name", "verified_at", "dashboard_url"],
        "profile-rejected" => vec!["first_name", "role_name", "rejection_reason", "profile_url"],
        "payment-success" => vec!["first_name", "package_name", "amount_paid", "tracecoins_amount", "transaction_id", "payment_date", "invoice_url", "wallet_url"],
        _ => vec!["first_name"],
    };

    (StatusCode::OK, Json(PreviewResponse {
        html: sample_html,
        subject: subject.to_string(),
        variables: vars.iter().map(|s| s.to_string()).collect(),
    }))
}

#[derive(Deserialize)]
struct TestEmailRequest {
    to_email: String,
    template_name: String,
    variables: serde_json::Value,
}

async fn send_test_email(
    State(state): State<AppState>,
    Json(req): Json<TestEmailRequest>,
) -> impl IntoResponse {
    // Extract first_name from variables or use default
    let first_name = req.variables
        .get("first_name")
        .and_then(|v| v.as_str())
        .unwrap_or("Test User");

    // Send test email based on template
    let result = match req.template_name.as_str() {
        "welcome" => {
            state.mail.send_welcome_email(&req.to_email, first_name).await
        }
        "verify-email" => {
            state.mail.send_verification_email(&req.to_email, first_name, "123456").await
        }
        "password-reset" => {
            state.mail.send_password_reset_email(&req.to_email, first_name, "123456").await
        }
        "profile-verified" => {
            state.mail.send_profile_verified_email(&req.to_email, first_name, "Photographer").await
        }
        "payment-success" => {
            state.mail.send_payment_success_email(
                &req.to_email, 
                first_name, 
                "Starter Pack", 
                99900, 
                100, 
                "TXN123456"
            ).await
        }
        _ => {
            return (StatusCode::BAD_REQUEST, Json(serde_json::json!({ 
                "error": "Template not supported for test emails" 
            })));
        }
    };

    match result {
        Ok(_) => (StatusCode::OK, Json(serde_json::json!({ "message": "Test email sent" }))),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({ "error": e.to_string() }))),
    }
}

// ── Email Configuration ───────────────────────────────────────────────────────

#[derive(Serialize, Deserialize)]
#[allow(dead_code)]
struct EmailConfig {
    provider: String,
    smtp_host: String,
    smtp_port: i32,
    smtp_secure: bool,
    smtp_username: String,
    #[serde(skip_serializing)]
    smtp_password: Option<String>,
    zeptomail_api_key: String,
    zeptomail_from_email: String,
    zeptomail_from_name: String,
    from_email: String,
    from_name: String,
    reply_to_email: Option<String>,
    enabled: bool,
}

#[derive(Serialize)]
struct EmailConfigResponse {
    provider: String,
    smtp_host: String,
    smtp_port: i32,
    smtp_secure: bool,
    smtp_username: String,
    from_email: String,
    from_name: String,
    reply_to_email: Option<String>,
    enabled: bool,
    zeptomail_configured: bool,
}

async fn get_email_config() -> impl IntoResponse {
    let provider = std::env::var("EMAIL_PROVIDER").unwrap_or_else(|_| "SMTP".to_string());
    let zeptomail_configured = std::env::var("ZEPTOMAIL_API_KEY").is_ok();

    let config = EmailConfigResponse {
        provider: provider.clone(),
        smtp_host: std::env::var("SMTP_HOST").unwrap_or_default(),
        smtp_port: std::env::var("SMTP_PORT").unwrap_or_else(|_| "587".to_string()).parse().unwrap_or(587),
        smtp_secure: std::env::var("SMTP_SECURE").unwrap_or_default().to_lowercase() == "true",
        smtp_username: std::env::var("SMTP_USER").unwrap_or_default(),
        from_email: if provider == "ZEPTOMAIL" {
            std::env::var("ZEPTOMAIL_FROM_EMAIL").unwrap_or_else(|_| "noreply@nxtgauge.com".to_string())
        } else {
            std::env::var("SMTP_FROM_EMAIL").unwrap_or_else(|_| "noreply@nxtgauge.com".to_string())
        },
        from_name: if provider == "ZEPTOMAIL" {
            std::env::var("ZEPTOMAIL_FROM_NAME").unwrap_or_else(|_| "NXTGAUGE".to_string())
        } else {
            std::env::var("SMTP_FROM_NAME").unwrap_or_else(|_| "NXTGAUGE".to_string())
        },
        reply_to_email: std::env::var("SMTP_REPLY_TO")
            .ok()
            .or_else(|| std::env::var("ZEPTOMAIL_REPLY_TO").ok()),
        enabled: (provider == "SMTP" && std::env::var("SMTP_HOST").is_ok())
            || (provider == "ZEPTOMAIL" && std::env::var("ZEPTOMAIL_API_KEY").is_ok()),
        zeptomail_configured,
    };

    (StatusCode::OK, Json(config))
}

#[derive(Deserialize)]
#[allow(dead_code)]
struct UpdateEmailConfigRequest {
    provider: String,
    smtp_host: String,
    smtp_port: i32,
    smtp_secure: bool,
    smtp_username: String,
    smtp_password: Option<String>,
    zeptomail_api_key: String,
    zeptomail_from_email: String,
    zeptomail_from_name: String,
    from_email: String,
    from_name: String,
    reply_to_email: Option<String>,
    enabled: bool,
}

async fn update_email_config(
    Json(req): Json<UpdateEmailConfigRequest>,
) -> impl IntoResponse {
    if req.enabled {
        if req.provider == "SMTP" && req.smtp_host.is_empty() {
            return (StatusCode::BAD_REQUEST, Json(serde_json::json!({
                "error": "SMTP host is required when SMTP provider is enabled"
            })));
        }
        if req.provider == "ZEPTOMAIL" && req.zeptomail_api_key.is_empty() {
            return (StatusCode::BAD_REQUEST, Json(serde_json::json!({
                "error": "Zeptomail API key is required when Zeptomail provider is enabled"
            })));
        }
    }

    (StatusCode::OK, Json(serde_json::json!({
        "message": "Email configuration updated. Restart services to apply changes.",
        "config": {
            "provider": req.provider,
            "smtp_host": req.smtp_host,
            "smtp_port": req.smtp_port,
            "smtp_secure": req.smtp_secure,
            "smtp_username": req.smtp_username,
            "zeptomail_api_key": if req.zeptomail_api_key.is_empty() { "[hidden]".to_string() } else { "[configured]".to_string() },
            "from_email": req.from_email,
            "from_name": req.from_name,
            "reply_to_email": req.reply_to_email,
            "enabled": req.enabled,
        }
    })))
}

#[derive(Deserialize)]
struct EmailTestRequest {
    to_email: String,
    #[allow(dead_code)]
    provider: Option<String>,
    config: Option<EmailTestConfig>,
}

#[derive(Deserialize)]
#[allow(dead_code)]
struct EmailTestConfig {
    provider: String,
    smtp_host: String,
    smtp_port: i32,
    smtp_secure: bool,
    smtp_username: String,
    smtp_password: String,
    zeptomail_api_key: String,
    from_email: String,
    from_name: String,
}

async fn test_email_connection(
    State(state): State<AppState>,
    Json(req): Json<EmailTestRequest>,
) -> impl IntoResponse {
    // Send a test email using current or provided config
    let result = if let Some(_test_config) = req.config {
        // For now, just use the existing mailer - test config would require recreating mailer
        state.mail.send_test_email(&req.to_email).await
    } else {
        // Use existing mailer
        state.mail.send_test_email(&req.to_email).await
    };

    match result {
        Ok(_) => (StatusCode::OK, Json(serde_json::json!({
            "message": "Test email sent successfully",
            "recipient": req.to_email
        }))),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({
            "error": format!("Failed to send test email: {}", e)
        }))),
    }
}
