

use std::fs;
use lettre::{Message, SmtpTransport, Transport};
use lettre::message::{Attachment, header, MultiPart, SinglePart};
use lettre::message::header::ContentType;
use lettre::transport::smtp::authentication::Credentials;
use crate::Connection;

#[derive(Clone)]
pub struct Smtp {

    name: String,
    mail: String,
    pass: String,

    host: String,
    port: String,

    to_name: String,
    to_mail: String,
    reply_to_name: String,
    reply_to_mail: String,
}
impl Smtp {
    pub fn new(config: Connection) -> Self {

        return Self {

            host: config.host,
            port: config.port,
            name: config.name,
            mail: config.mail,
            pass: config.pass,

            to_name: String::new(),
            to_mail: String::new(),
            reply_to_name: String::new(),
            reply_to_mail: String::new(),
        };
    }

    /// 设置发件人名称
    pub fn set_send_name(&mut self, send_name: &str) -> &mut Self {
        self.name = send_name.to_string();
        self
    }

    /// 收件人
    /// * name 收件人名称
    /// * mail 收件箱
    pub fn to(&mut self, name: &str, mail: &str) -> &mut Self {
        self.to_name = name.to_string();
        self.to_mail = mail.to_string();
        self
    }
    /// 抄送人
    /// * name 收件人名称
    /// * mail 收件箱
    pub fn reply_to(&mut self, name: &str, mail: &str) -> &mut Self {
        self.reply_to_name = name.to_string();
        self.reply_to_mail = mail.to_string();
        self
    }

    /// 附件
    pub fn add_file(&mut self, path: &str, name: &str, content_type: &str) -> SinglePart {
        let content_type = {
            match content_type {
                "pdf" => {
                    ContentType::parse("application/pdf").unwrap()
                }
                "html" => {
                    ContentType::parse("text/html").unwrap()
                }
                "jpeg" => {
                    ContentType::parse("image/jpeg").unwrap()
                }
                "json" => {
                    ContentType::parse("application/json").unwrap()
                }
                _ => {
                    ContentType::parse("text/plain").unwrap()
                }
            }
        };
        return Attachment::new(name.to_string()).body(fs::read(path.clone()).unwrap(), content_type);
    }
    /// 发送
    ///
    /// * subject 主题
    /// * body 内容
    pub fn send(&mut self, subject: &str, body: &str, files: Vec<SinglePart>) -> bool {

        let mut builder = Message::builder().from(format!("{} <{}>", self.name, self.mail).parse().unwrap()).subject(subject);
        builder = builder.to(format!("{} <{}>", self.to_name, self.to_mail).parse().unwrap());
        if !self.reply_to_name.is_empty() {
            builder = builder.reply_to(format!("{} <{}>", self.reply_to_name, self.reply_to_mail).parse().unwrap());
        }

        let mut body = MultiPart::alternative().multipart(
            MultiPart::alternative_plain_html(String::from("text/plain"), String::from(body))
        ).singlepart(SinglePart::builder().header(header::ContentType::TEXT_PLAIN).body(String::from(body)));

        if !files.is_empty() {
            for file in files.iter() {
                body = body.singlepart(file.clone()).clone();
            }
        }

        let email = builder.multipart(body.clone()).unwrap();

        let mailer = SmtpTransport::relay(self.host.as_str())
            .unwrap()
            .port(self.port.parse::<u16>().unwrap())
            .credentials(Credentials::new(self.mail.to_string(), self.pass.to_string()))
            .build();
        match mailer.send(&email) {
            Ok(_) => {
                true
            }
            Err(e) => {
                println!("错误: {}", e);
                false
            }
        }
    }
}