//! Email template system for pre-defined email formats

use std::collections::HashMap;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum TemplateError {
    #[error("Template not found: {0}")]
    NotFound(String),
    #[error("Missing required variable: {0}")]
    MissingVariable(String),
}

/// Email template definition
#[derive(Debug, Clone)]
pub struct EmailTemplate {
    pub id: String,
    pub name: String,
    pub description: String,
    pub subject_template: String,
    pub body_template: String,
    /// Default values for template variables
    pub default_variables: HashMap<String, String>,
    /// Content type (text/html or text/plain)
    pub content_type: String,
}

impl EmailTemplate {
    /// Render the template with provided variables
    pub fn render(&self, variables: &HashMap<String, String>) -> Result<(String, String), TemplateError> {
        let subject = self.substitute_variables(&self.subject_template, variables)?;
        let body = self.substitute_variables(&self.body_template, variables)?;
        Ok((subject, body))
    }

    /// Get list of variable names in this template
    pub fn variable_names(&self) -> Vec<String> {
        self.default_variables.keys().cloned().collect()
    }

    fn substitute_variables(&self, template: &str, variables: &HashMap<String, String>) -> Result<String, TemplateError> {
        let mut result = template.to_string();

        // First pass: substitute provided variables
        for (key, value) in variables {
            let placeholder = format!("{{{{{}}}}}", key);
            result = result.replace(&placeholder, value);
        }

        // Second pass: substitute defaults for any remaining placeholders
        for (key, default_value) in &self.default_variables {
            let placeholder = format!("{{{{{}}}}}", key);
            if result.contains(&placeholder) {
                result = result.replace(&placeholder, default_value);
            }
        }

        Ok(result)
    }
}

/// Registry of available email templates
pub struct EmailTemplateRegistry {
    templates: HashMap<String, EmailTemplate>,
}

impl Default for EmailTemplateRegistry {
    fn default() -> Self {
        Self::new()
    }
}

impl EmailTemplateRegistry {
    /// Create a new registry with built-in templates
    pub fn new() -> Self {
        let mut registry = Self {
            templates: HashMap::new(),
        };

        // Register built-in templates
        registry.register(Self::Nexus_notification());
        registry.register(Self::service_scheduled());
        registry.register(Self::project_update());
        registry.register(Self::invoice_ready());
        registry.register(Self::payment_received());

        registry
    }

    /// Register a custom template
    pub fn register(&mut self, template: EmailTemplate) {
        self.templates.insert(template.id.clone(), template);
    }

    /// Get a template by ID
    pub fn get(&self, template_id: &str) -> Option<&EmailTemplate> {
        self.templates.get(template_id)
    }

    /// List all available templates
    pub fn list(&self) -> Vec<&EmailTemplate> {
        self.templates.values().collect()
    }

    /// List template IDs
    pub fn list_ids(&self) -> Vec<String> {
        self.templates.keys().cloned().collect()
    }

    // Built-in templates

    fn Nexus_notification() -> EmailTemplate {
        EmailTemplate {
            id: "Nexus_notification".to_string(),
            name: "Nexus Notification".to_string(),
            description: "General notification from Nexus".to_string(),
            subject_template: "{{subject}}".to_string(),
            body_template: r#"<!DOCTYPE html>
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<p>Hi {{recipient_name}},</p>

<p>{{message}}</p>

<p>Thanks,<br>
Nexus Team</p>
</body>
</html>"#.to_string(),
            default_variables: HashMap::from([
                ("subject".to_string(), "Notification from Nexus".to_string()),
                ("recipient_name".to_string(), "Team Member".to_string()),
                ("message".to_string(), "This is a notification message.".to_string()),
            ]),
            content_type: "text/html".to_string(),
        }
    }

    fn service_scheduled() -> EmailTemplate {
        EmailTemplate {
            id: "service_scheduled".to_string(),
            name: "Service Scheduled".to_string(),
            description: "Notification when a service is scheduled".to_string(),
            subject_template: "Service Scheduled - {{customer_name}}".to_string(),
            body_template: r#"<!DOCTYPE html>
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<p>Hi {{recipient_name}},</p>

<p>A new service has been scheduled:</p>

<table style="border-collapse: collapse; margin: 20px 0;">
<tr>
  <td style="padding: 8px; font-weight: bold;">Customer:</td>
  <td style="padding: 8px;">{{customer_name}}</td>
</tr>
<tr>
  <td style="padding: 8px; font-weight: bold;">Date:</td>
  <td style="padding: 8px;">{{service_date}}</td>
</tr>
<tr>
  <td style="padding: 8px; font-weight: bold;">Address:</td>
  <td style="padding: 8px;">{{service_address}}</td>
</tr>
</table>

<p>Please check the Nexus system for full details.</p>

<p>Thanks,<br>
Nexus Dispatch Team</p>
</body>
</html>"#.to_string(),
            default_variables: HashMap::from([
                ("recipient_name".to_string(), "Team Member".to_string()),
                ("customer_name".to_string(), "Customer".to_string()),
                ("service_date".to_string(), "TBD".to_string()),
                ("service_address".to_string(), "TBD".to_string()),
            ]),
            content_type: "text/html".to_string(),
        }
    }

    fn project_update() -> EmailTemplate {
        EmailTemplate {
            id: "project_update".to_string(),
            name: "Project Update".to_string(),
            description: "Notification about project status changes".to_string(),
            subject_template: "Project Update - {{project_name}}".to_string(),
            body_template: r#"<!DOCTYPE html>
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<p>Hi {{recipient_name}},</p>

<p><strong>Project Status Update</strong></p>

<table style="border-collapse: collapse; margin: 20px 0;">
<tr>
  <td style="padding: 8px; font-weight: bold;">Project:</td>
  <td style="padding: 8px;">{{project_name}}</td>
</tr>
<tr>
  <td style="padding: 8px; font-weight: bold;">Status:</td>
  <td style="padding: 8px;">{{project_status}}</td>
</tr>
</table>

<p>{{message}}</p>

<p>View details in the Nexus system.</p>

<p>Thanks,<br>
Nexus Team</p>
</body>
</html>"#.to_string(),
            default_variables: HashMap::from([
                ("recipient_name".to_string(), "Team Member".to_string()),
                ("project_name".to_string(), "Project".to_string()),
                ("project_status".to_string(), "Updated".to_string()),
                ("message".to_string(), "".to_string()),
            ]),
            content_type: "text/html".to_string(),
        }
    }

    fn invoice_ready() -> EmailTemplate {
        EmailTemplate {
            id: "invoice_ready".to_string(),
            name: "Invoice Ready".to_string(),
            description: "Notification when an invoice is ready for a customer".to_string(),
            subject_template: "Invoice Ready - {{invoice_period}}".to_string(),
            body_template: r#"<!DOCTYPE html>
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<p>Hi {{recipient_name}},</p>

<p>Your invoice for {{invoice_period}} is now available.</p>

<table style="border-collapse: collapse; margin: 20px 0;">
<tr>
  <td style="padding: 8px; font-weight: bold;">Period:</td>
  <td style="padding: 8px;">{{invoice_period}}</td>
</tr>
<tr>
  <td style="padding: 8px; font-weight: bold;">Amount:</td>
  <td style="padding: 8px;">{{invoice_amount}}</td>
</tr>
</table>

<p>{{message}}</p>

<p>Thanks for your business,<br>
Acme Services</p>
</body>
</html>"#.to_string(),
            default_variables: HashMap::from([
                ("recipient_name".to_string(), "Valued Customer".to_string()),
                ("invoice_period".to_string(), "Current Period".to_string()),
                ("invoice_amount".to_string(), "$0.00".to_string()),
                ("message".to_string(), "Please let us know if you have any questions.".to_string()),
            ]),
            content_type: "text/html".to_string(),
        }
    }

    fn payment_received() -> EmailTemplate {
        EmailTemplate {
            id: "payment_received".to_string(),
            name: "Payment Received".to_string(),
            description: "Confirmation when a payment is received".to_string(),
            subject_template: "Payment Received - Thank You!".to_string(),
            body_template: r#"<!DOCTYPE html>
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
<p>Hi {{recipient_name}},</p>

<p>We've received your payment. Thank you!</p>

<table style="border-collapse: collapse; margin: 20px 0;">
<tr>
  <td style="padding: 8px; font-weight: bold;">Amount:</td>
  <td style="padding: 8px;">{{payment_amount}}</td>
</tr>
<tr>
  <td style="padding: 8px; font-weight: bold;">Date:</td>
  <td style="padding: 8px;">{{payment_date}}</td>
</tr>
</table>

<p>{{message}}</p>

<p>Thanks for your business,<br>
Acme Services</p>
</body>
</html>"#.to_string(),
            default_variables: HashMap::from([
                ("recipient_name".to_string(), "Valued Customer".to_string()),
                ("payment_amount".to_string(), "$0.00".to_string()),
                ("payment_date".to_string(), "Today".to_string()),
                ("message".to_string(), "".to_string()),
            ]),
            content_type: "text/html".to_string(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_template_render() {
        let template = EmailTemplateRegistry::new();
        let notif = template.get("Nexus_notification").unwrap();

        let vars = HashMap::from([
            ("subject".to_string(), "Test Subject".to_string()),
            ("recipient_name".to_string(), "John".to_string()),
            ("message".to_string(), "Hello, world!".to_string()),
        ]);

        let (subject, body) = notif.render(&vars).unwrap();
        assert_eq!(subject, "Test Subject");
        assert!(body.contains("Hi John,"));
        assert!(body.contains("Hello, world!"));
    }

    #[test]
    fn test_template_defaults() {
        let template = EmailTemplateRegistry::new();
        let notif = template.get("Nexus_notification").unwrap();

        let vars = HashMap::new();
        let (subject, body) = notif.render(&vars).unwrap();

        assert_eq!(subject, "Notification from Nexus");
        assert!(body.contains("Hi Team Member,"));
    }
}
