use crate::{Authorization, Connection, ContentType, Encoding, HttpError, Language, Method, Upgrade, Uri};
use crate::config::{Config};
use chrono::{DateTime, Local};
use json::{array, object, JsonValue};
use log::{info};
use std::io::{Write};
use std::path::{Path};
use std::{env, fs, io, thread};
use std::cmp::PartialEq;
use std::fs::OpenOptions;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use crate::stream::{Protocol, Scheme};

/// 请求体
#[derive(Clone, Debug)]
pub struct Request {
    pub config: Config,
    /// 协议版本
    pub protocol: Protocol,
    /// 当前请求类型
    pub method: Method,
    /// 资源标识符
    pub uri: Uri,
    /// 源站
    pub origin: String,
    /// header信息
    pub header: JsonValue,
    /// Cookie信息
    pub cookie: JsonValue,
    /// 查询参数
    pub query: JsonValue,
    /// 请求参数
    pub params: JsonValue,
    /// 认证信息
    pub authorization: Authorization,
    /// 处理耗时
    pub handle_time: String,
    /// 请求时间
    pub datetime: String,
    /// 请求时间戳
    pub timestamp: i64,
    /// 客户端IP
    pub client_ip: String,
    /// 代理端IP
    pub proxy_ip: String,
    /// 服务端IP
    pub server_ip: String,
    // 升级协议
    pub upgrade: Upgrade,
    /// 连接方式
    pub connection: Connection,
    /// 压缩方式
    pub accept_encoding: Encoding,
    /// 开始时间
    start_time: Instant,
    /// 请求体数据
    pub body_data: Vec<u8>,
    /// 消息体长度
    content_length: usize,
    /// 消息体类型
    pub content_type: ContentType,
    /// 边界
    boundary: String,
    pub scheme: Arc<Mutex<Scheme>>,
    /// 接受语音
    pub accept_language: Language,
}


impl Request {
    pub fn new(config: Config, scheme: Arc<Mutex<Scheme>>) -> Self {

        // 获取请求客户端IP
        let client_ip = scheme.lock().unwrap().client_ip();
        // 获取服务端IP
        let server_ip = scheme.lock().unwrap().server_ip();
        let local: DateTime<Local> = Local::now();
        Self {
            config,
            protocol: Protocol::Other(String::new()),
            method: Method::Other(String::new()),
            uri: Uri::default(),
            origin: "".to_string(),
            header: object! {},
            cookie: object! {},
            query: object! {},
            params: object! {},
            authorization: Authorization::Other(String::new()),
            handle_time: String::new(),
            scheme,
            start_time: Instant::now(),
            datetime: local.format("%Y-%m-%d %H:%M:%S").to_string(),
            timestamp: local.timestamp(),
            client_ip,
            server_ip,
            proxy_ip: String::new(),
            upgrade: Upgrade::Other(String::new()),
            connection: Connection::Other(String::new()),
            accept_encoding: Encoding::None,
            body_data: vec![],
            content_length: 0,
            content_type: ContentType::Other(String::new()),
            boundary: String::new(),
            accept_language: Language::ZhCN,
        }
    }

    pub fn handle(&mut self) -> Result<(), HttpError> {

        // 读开始行
        {
            let header_line = self.scheme.lock().unwrap().read_line()?;
            self.handle_header_line(header_line.trim())?;
            //data = self.scheme.lock().unwrap().read()?;
            //if let Some(pos) = data.windows(2).position(|window| window == [13, 10]) {
            //    let header_data = data.drain(..pos).collect::<Vec<u8>>();
            //    data.drain(..2);
            //    let header_data = String::from_utf8_lossy(header_data.as_slice());
            //    self.handle_header_line(header_data.trim())?;
            //} else if data.len() < 1024 * 1024 {
            //    return Err(HttpError::new(400, "请求行错误"));
            //}
        }

        // 请求头处理
        match &self.protocol {
            Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
                {
                    loop {
                        let mut data = self.scheme.lock().unwrap().read()?;
                        if let Some(pos) = data.windows(4).position(|window| window == [13, 10, 13, 10]) {
                            self.handle_header(data.drain(..pos).collect::<Vec<u8>>())?;
                            data.drain(..4);
                            self.body_data = data;
                            break;
                        } else {
                            continue;
                        }
                    }
                }
                // 消息体处理
                {
                    if self.content_length > 0 {
                        loop {
                            if self.body_data.len() >= self.content_length {
                                break;
                            }
                            self.body_data.extend(self.scheme.lock().unwrap().read()?);
                        }
                        self.handle_body(self.body_data.clone())?;
                    }
                }
                self.handle_time = format!("{:?}", self.start_time.elapsed());
            }
            Protocol::HTTP2 => {
                let mut data = vec![];
                data.extend(self.scheme.lock().unwrap().read()?);
                let header = data.drain(..8).collect::<Vec<u8>>();
                if header.ne(b"\r\nSM\r\n\r\n") {
                    return Err(HttpError::new(400, "HTTP2格式错误"));
                }
                let scheme_arc = self.scheme.clone();
                let mut scheme = scheme_arc.lock().unwrap();
                scheme.http2_handle_header(&mut data, self)?;
                self.body_data = scheme.http2_handle_body(&mut data, self.clone())?;
                self.handle_body(self.body_data.clone())?;
                self.handle_time = format!("{:?}", self.start_time.elapsed());
            }
            Protocol::HTTP3 => return Err(HttpError::new(500, format!("未支持: HTTP3 {:?}", self.protocol).as_str())),
            Protocol::Other(e) => return Err(HttpError::new(500, format!("未支持: Other {e} {:?}", self.protocol).as_str())),
        }
        Ok(())
    }
    /// 处理请求行
    pub fn handle_header_line(&mut self, line: &str) -> Result<(), HttpError> {
        let line = br_crypto::encoding::urlencoding_decode(line);
        if line.is_empty() {
            return Err(HttpError::new(400, "请求行错误"));
        }
        if self.config.debug {
            info!("\r\n=================请求行 {:?}=================\r\n{line}\r\n========================================",thread::current().id());
        }
        let mut it = line.split_whitespace();
        let method = it.next();
        let target = it.next();
        let version = it.next();

        // 处理协议版本
        self.protocol = match version {
            None => return Err(HttpError::new(400, "协议版本错误")),
            Some(e) => Protocol::from(e)
        };
        // 根据版本分别处理
        match &self.protocol {
            Protocol::HTTP1_0 => {
                self.method = match method {
                    None => return Err(HttpError::new(400, "请求类型错误")),
                    Some(e) => Method::from(e)
                };
                self.uri = match target {
                    None => return Err(HttpError::new(400, "请求资源错误")),
                    Some(e) => Uri::from(e)
                };
                self.query = self.uri.get_query_params();
            }
            Protocol::HTTP1_1 => {
                self.method = match method {
                    None => return Err(HttpError::new(400, "请求类型错误")),
                    Some(e) => Method::from(e)
                };
                self.uri = match target {
                    None => return Err(HttpError::new(400, "请求资源错误")),
                    Some(e) => Uri::from(e)
                };
                self.query = self.uri.get_query_params();
            }
            Protocol::HTTP2 => {}
            Protocol::HTTP3 => return Err(HttpError::new(400, format!("{:?}协议暂未实现", self.protocol).as_str())),
            Protocol::Other(name) => return Err(HttpError::new(400, format!("{name}协议暂未实现").as_str())),
        }
        Ok(())
    }
    pub fn handle_header(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
        let headers = String::from_utf8_lossy(data.as_slice());
        if self.config.debug {
            info!("\r\n=================请求头 {:?}=================\r\n{headers}\r\n========================================",thread::current().id());
        }
        match &self.protocol {
            Protocol::HTTP1_0 => {
                for item in headers.lines() {
                    self.header_line_set(item)?;
                }
            }
            Protocol::HTTP1_1 => {
                for item in headers.lines() {
                    self.header_line_set(item)?;
                }
                if !self.header.has_key("host") {
                    return Err(HttpError::new(400, "请求头错误"));
                }
            }
            Protocol::HTTP2 => {
                return Err(HttpError::new(400, "HTTP2格式错误"));
            }
            Protocol::HTTP3 => return Err(HttpError::new(400, "暂时未开放")),
            Protocol::Other(name) => {
                return Err(HttpError::new(400, format!("未知协议格式: {}", name).as_str()));
            }
        }
        Ok(())
    }

    fn header_line_set(&mut self, line: &str) -> Result<(), HttpError> {
        match line.trim().find(":") {
            None => return Err(HttpError::new(400, format!("请求头[{line}]错误").as_str())),
            Some(e) => {
                let key = line[..e].trim().to_lowercase().clone();
                let value = line[e + 1..].trim();
                self.set_header(key.as_str(), value)?;
            }
        }
        Ok(())
    }
    pub fn set_header(&mut self, key: &str, value: &str) -> Result<(), HttpError> {
        self.header[key] = value.into();
        if value.len() > 8192 {
            return Err(HttpError::new(400, "header longer than 8192 characters"));
        }
        match key {
            "origin" => self.origin = value.to_string(),
            "content-type" => {
                let t = value.split_whitespace().collect::<Vec<&str>>();
                if !t.is_empty() {
                    match t[0] {
                        _ if t[0].contains("multipart/form-data") => {
                            self.boundary = t[1].trim().trim_start_matches("boundary=").to_string();
                            self.content_type = ContentType::from("multipart/form-data");
                        }
                        _ => {
                            self.content_type = ContentType::from(t[0].trim_end_matches(";"));
                        }
                    }
                }
                self.header[key] = self.content_type.str().into();
            }
            "content-length" => self.content_length = value.parse::<usize>().unwrap_or(0),
            "accept-language" => self.accept_language = Language::from(value),
            "authorization" => self.authorization = Authorization::from(value),
            "upgrade" => self.upgrade = Upgrade::from(value),
            "connection" => self.connection = Connection::from(value),
            "accept-encoding" => self.accept_encoding = Encoding::from(value),
            "cookie" => {
                let _ = value.split(';').collect::<Vec<&str>>().iter().map(|&x| {
                    match x.find('=') {
                        None => {}
                        Some(index) => {
                            let key = x[..index].trim().to_string();
                            let val = x[index + 1..].trim().to_string();
                            let _ = self.cookie.insert(key.as_str(), val);
                        }
                    }
                    ""
                }).collect::<Vec<&str>>();
            }
            "x-forwarded-for" => self.proxy_ip = value.to_string(),
            "x-real-ip" => self.client_ip = value.to_string(),
            _ => {}
        }

        Ok(())
    }
    pub fn handle_body(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
        if self.config.debug {
            info!("\r\n=================请求体 {:?}=================\r\n长度: {}\r\n========================================",thread::current().id(),self.content_length);
        }
        if data.len() != self.content_length {
            return Err(HttpError::new(400, format!("Content-Length mismatch: header={}, actual={}", self.content_length, data.len()).as_str()));
        }
        if self.content_length == 0 {
            return Ok(());
        }
        match &self.content_type {
            ContentType::FormData => {
                let boundary_marker = format!("--{}", self.boundary);
                let parts = split_vec_u8(&data, boundary_marker.as_bytes());

                let mut fields = object! {};

                for part in parts {
                    let (header, body) = match part.windows(b"\r\n\r\n".len()).position(|window| window == b"\r\n\r\n") {
                        None => continue,
                        Some(_) => {
                            let mut re = split_vec_u8(part.as_slice(), "\r\n\r\n".as_bytes());
                            let header = re[0].clone();
                            let t = re[1].len() - 2;
                            let body = re[1].drain(..t).collect::<Vec<u8>>();
                            (header, body)
                        }
                    };
                    let headers = String::from_utf8_lossy(header.as_slice());
                    let mut field_name = "";
                    let mut filename = "";
                    let mut content_type = ContentType::Other("".to_string());

                    for header in headers.lines() {
                        if header.to_lowercase().starts_with("content-disposition:") {
                            match header.find("filename=\"") {
                                None => {}
                                Some(filename_start) => {
                                    let filename_len = filename_start + 10;
                                    let filename_end = header[filename_len..].find('"').unwrap() + filename_len;
                                    filename = &header[filename_len..filename_end];
                                }
                            }
                            match header.find("name=\"") {
                                None => {}
                                Some(name_start) => {
                                    let name_start = name_start + 6;
                                    let name_end = header[name_start..].find('"').unwrap() + name_start;
                                    field_name = &header[name_start..name_end];
                                }
                            }
                        }
                        if header.to_lowercase().starts_with("content-type:") {
                            content_type = ContentType::from(header.to_lowercase().trim_start_matches("content-type:").trim());
                        }
                    }

                    if filename.is_empty() {
                        let text = String::from_utf8_lossy(body.as_slice());
                        fields[field_name.to_string()] = JsonValue::from(text.into_owned());
                        continue;
                    }
                    let extension = Path::new(filename).extension().and_then(|ext| ext.to_str()); // 转换为 &str
                    let suffix = extension.unwrap_or("txt");
                    let filename = if extension.is_none() {
                        format!("{filename}.txt")
                    } else {
                        filename.to_string()
                    };

                    let mut temp_dir = env::temp_dir();
                    temp_dir.push(filename.clone());
                    let Ok(mut temp_file) = fs::File::create(&temp_dir) else { continue };
                    if temp_file.write(body.as_slice()).is_ok() {
                        if fields[field_name.to_string()].is_empty() {
                            fields[field_name.to_string()] = array![];
                        }
                        fields[field_name.to_string()].push(object! {
                                        id:br_crypto::sha256::encrypt_hex(&body.clone()),
                                        name:filename,
                                        suffix:suffix,
                                        size:body.len(),
                                        type:content_type.str(),
                                        file:temp_dir.to_str()
                                    }).unwrap();
                    }
                }
                self.params = fields;
            }
            ContentType::FormUrlencoded => {
                let input = String::from_utf8_lossy(&data);
                let mut list = object! {};
                for pair in input.split('&') {
                    if let Some((key, val)) = pair.split_once('=') {
                        let key = br_crypto::encoding::urlencoding_decode(key);
                        let val = br_crypto::encoding::urlencoding_decode(val);
                        let _ = list.insert(key.as_str(), val);
                    }
                }
                self.params = list;
            }
            ContentType::Json => {
                let text = String::from_utf8_lossy(data.as_slice());
                self.params = json::parse(text.into_owned().as_str()).unwrap_or(object! {});
            }
            ContentType::Xml | ContentType::Html | ContentType::Text | ContentType::Javascript => {
                let text = String::from_utf8_lossy(data.as_slice());
                self.params = text.into_owned().into();
            }
            ContentType::Other(_) => {}
            ContentType::Stream => {}
        }
        Ok(())
    }
    /// 保存日志
    pub fn save_log(&mut self) -> io::Result<()> {
        if !self.config.log {
            return Ok(());
        }
        let local: DateTime<Local> = Local::now();
        let time_dir = local.format("%Y-%m-%d-%H").to_string();
        let time_dir = time_dir.split('-').collect::<Vec<&str>>();

        let mut res = self.config.root_path.join(self.config.runtime.clone()).join("log");
        for item in &time_dir {
            res.push(item);
        }
        fs::create_dir_all(res.parent().unwrap())?;
        let log_file = format!("{}.log", res.to_str().unwrap());
        let mut file = OpenOptions::new()
            // 允许写入
            .append(true) // 追加内容到文件末尾
            .create(true) // 如果文件不存在，则创建
            .open(log_file)?;
        let data = format!(
            "[{}] {} ClientIP: {} {} {} ContentLength: {} ContentType: {} Time: {:?}\r\n",
            self.datetime,
            self.protocol.str(),
            self.client_ip,
            self.method.str(),
            self.uri.url,
            self.content_length,
            self.content_type.clone().str(),
            self.handle_time
        );
        file.write_all(data.as_bytes())?;
        Ok(())
    }
}

fn split_vec_u8(data: &[u8], delimiter: &[u8]) -> Vec<Vec<u8>> {
    let mut parts = Vec::new();
    let mut start = 0;
    let mut i = 0;

    while i <= data.len().saturating_sub(delimiter.len()) {
        if &data[i..i + delimiter.len()] == delimiter {
            parts.push(data[start..i].to_vec());
            i += delimiter.len();
            start = i;
        } else {
            i += 1;
        }
    }
    // 剩下的部分
    if start <= data.len() {
        parts.push(data[start..].to_vec());
    }
    parts
}

