use std::{fs};
use std::net::TcpStream;
use std::path::Path;
use br_crypto::base64::{encode_file, encode_mail};
use crate::{Connection};
use br_file;
use log::info;

pub mod analysis;

#[derive(Clone)]
pub struct Imap {
    host: String,
    port: String,

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

    // total_mail: i32,
    // total_size: i64,
}

impl Imap {
    pub fn new(config: Connection) -> Self {
        Self {
            host: config.host,
            port: config.port,
            // name: config.name,
            mail: config.mail,
            pass: config.pass,
            // total_mail: 0,
            // total_size: 0,
        }
    }
    pub fn connect(&mut self) -> String {
        let client = imap::ClientBuilder::new(self.host.clone(), self.port.parse::<u16>().unwrap()).native_tls().unwrap();
        let imap_session = client
            .login(self.mail.clone(), self.pass.clone())
            .map_err(|e| e.0);
        let mut imap_session = match imap_session {
            Ok(e) => e,
            Err(e) => {
                println!("{:#?}", e);
                return "aaa".to_string();
            }
        };


        imap_session.select("INBOX").unwrap();

        let messages = imap_session.fetch("5", "RFC822").unwrap(); // RFC822 第5封邮件有qp解码bug
        let message = if let Some(m) = messages.iter().next() {
            m
        } else {
            return "bbb".to_string();
        };

        let body = message.body().expect("message did not have a body!");


        // 尝试将字节数组直接转换为 UTF-8 格式的 Rust 字符串
        let data = match std::str::from_utf8(body) {
            Ok(str) => str.to_owned(),
            Err(_) => {
                // 如果转换失败，则说明字节数组可能采用其它编码格式，使用 gbk_to_utf8 方法转换为 UTF-8 格式的 Rust 字符串
                let gbk_str = br_crypto::encoding::code_to_utf8("", body.to_vec());
                gbk_str
            }
        };
        // println!(">>>>>>{}", data);

        // be nice to the server and log out
        imap_session.logout().unwrap();


        return data;
    }
    pub fn connect_p(&mut self) {
        let stream = TcpStream::connect(format!("{}:{}", self.host.clone(), self.port.clone())).unwrap();
        let mut client = imap::Client::new(stream);
        client.read_greeting().unwrap();
        eprintln!("\nUNENCRYPTED connection made!!!!\n");
        eprintln!("This is highly not recommended.\n");
        // to do anything useful with the e-mails, we need to log in
        // keep in mind that this is over plain TCP, so may leak all your secrets!
        let mut imap_session = client
            .login(self.mail.clone(), self.pass.clone()).unwrap();

        // we want to fetch the first email in the INBOX mailbox
        imap_session.select("INBOX").unwrap();

        // fetch message number 1 in this mailbox, along with its RFC822 field.
        // RFC 822 dictates the format of the body of e-mails
        let messages = imap_session.fetch("2", "RFC822").unwrap();
        let message = if let Some(m) = messages.iter().next() {
            m
        } else {
            println!("1111");
            return;
        };

        let body = message.body().expect("message did not have a body!");
        let data = String::from_utf8_lossy(body).to_string();
        println!(">>>>>>{}", data);

        imap_session.logout().unwrap();
        return;
    }

    pub fn connect_t(&mut self) {
        let client = imap::ClientBuilder::new(self.host.clone(), self.port.parse::<u16>().unwrap()).rustls().unwrap();
        let mut imap_session = client.login(self.mail.clone(), self.pass.clone()).map_err(|e| e.0).unwrap();

        // we want to fetch the first email in the INBOX mailbox
        imap_session.select("INBOX").unwrap();

        // fetch message number 1 in this mailbox, along with its RFC822 field.
        // RFC 822 dictates the format of the body of e-mails
        let messages = imap_session.fetch("1", "RFC822").unwrap();
        let message = if let Some(m) = messages.iter().next() {
            m
        } else {
            return;
        };

        let body = message.body().expect("message did not have a body!");
        let data = String::from_utf8_lossy(body).to_string();
        println!("{}", data);

        imap_session.logout().unwrap();
    }

    pub fn connect_listen(&mut self) {
        let client = imap::ClientBuilder::new(self.host.clone(), self.port.parse::<u16>().unwrap()).rustls().unwrap();
        let mut imap = client.login(self.mail.clone(), self.pass.clone()).map_err(|e| e.0).unwrap();
        imap.debug = true;
        // we want to fetch the first email in the INBOX mailbox
        imap.select("INBOX").unwrap();

        let mut num_responses = 0;
        let max_responses = 6000;
        let idle_result = imap.idle().wait_while(|response| {
            num_responses += 1;
            println!("IDLE response #{}: {:?}", num_responses, response);
            if num_responses >= max_responses {
                // Stop IDLE
                false
            } else {
                // Continue IDLE
                true
            }
        });

        match idle_result {
            Ok(reason) => println!("IDLE finished normally {:?}", reason),
            Err(e) => println!("IDLE finished with error {:?}", e),
        }

        imap.logout().unwrap();
    }

    /// 获取邮箱中所有邮件列表
    pub fn connect_totals(&mut self) -> (String, String) {
        let client = imap::ClientBuilder::new(self.host.clone(), match self.port.parse::<u16>() {
            Ok(e) => e,
            Err(_) => {return (self.mail.clone(), "port端口号 格式错误! 请输入数字!".to_string());}
        }).rustls();
        let client = match client {
            Ok(e) => e,
            Err(_) => {
                return (self.mail.clone(), "host 服务器地址 or port 端口号错误!".to_string());
            }
        };
        let mut imap = match client.login(self.mail.clone(), self.pass.clone()) {
            Ok(e) => e,
            Err(_) => {
                return (self.mail.clone(), "mail or pass 错误! 或者没有开启邮箱IMAP服务器!".to_string());
            }
        };
        // imap.debug = true;
        let t = imap.select("INBOX").unwrap();
        imap.logout().unwrap();
        (self.mail.clone(), t.exists.to_string())
    }

    /// 下载指定邮件, 邮箱编号, id_list就是邮件id队列
    pub fn download_totals(&mut self, mail_account_id: String, id_list: Vec<u32>, save_address: String, group_num: usize, fun: fn(mail: String, id: u32, name: String)) -> (String, String) {
        let client = imap::ClientBuilder::new(self.host.clone(), match self.port.parse::<u16>() {
            Ok(e) => e,
            Err(_) => {return (self.mail.clone(), "port端口号 格式错误! 请输入数字!".to_string());}
        }).rustls();
        let client = match client {
            Ok(e) => e,
            Err(_) => {
                return (self.mail.clone(), "host 服务器地址 or port 端口号错误!".to_string());
            }
        };
        let mut imap = match client.login(self.mail.clone(), self.pass.clone()) {
            Ok(e) => e,
            Err(_) => {
                return (self.mail.clone(), "mail or pass 错误! 或者没有开启邮箱IMAP服务器!".to_string());
            }
        };

        //---↓--- must select!
        imap.select("INBOX").unwrap();
        //---↑---

        // 邮件保存
        let temp = self.mail.clone();
        let mail_name: Vec<&str> = temp.split("@").collect();
        let create_name = format!("{}\\{}", save_address, mail_name[0]);
        br_file::create_dir(create_name.as_str());

        for i in id_list {
            let id = format!("\"{}\"", i.clone());
            let messages = match imap.fetch(id, "RFC822") {
                Ok(e) => e,
                Err(e) => {
                    info!("fetch err! {}", e.to_string());
                    continue;
                }
            };
            let mut data = vec![];
            for item in messages.iter() {
                if let Some(value) = item.body() {
                    let value_vec = Vec::from(&value[..]);
                    data.extend_from_slice(&value_vec[..]);
                }
            }
            // 处理存储的邮件名
            let h = br_crypto::hash::u8_to_md5(data.clone());
            let sec_dir_name = &h[..2].to_string();
            let sec_dir_path = format!("{}\\{}", create_name, sec_dir_name);
            br_file::create_dir(sec_dir_path.as_str());
            let email_name = format!("{}\\{}", sec_dir_path, h);

            // 加密邮件
            let final_data = encode_mail(h.clone(), data, group_num);

            // 存储加密后的邮件
            fs::write(email_name.clone(), final_data).expect("fail to write!");
            // 存储邮件原文件
            // fs::write(email_name.clone(), data).expect("fail to write!");

            // 检验是否存储成功
            let p = Path::new(email_name.as_str());
            if p.is_file() {
                fun(mail_account_id.clone(), i.clone(), h.clone());
            } else {
                info!(">>>>>>>>>>> can't find local file!");
            }
        }
        imap.logout().unwrap();
        (self.mail.clone(), "下载完成!".to_string())
    }
}
