use crate::base64::{decode, sha_256};
use crate::config::{Config};
use crate::encoding::Encoding;
use chrono::{DateTime, Local};
use json::{array, object, JsonValue};
use log::{error, info, warn};
use std::io::{Error, Write};
use std::path::{Path, PathBuf};
use std::str::Lines;
use std::{env, fs, io};
use std::fs::OpenOptions;
use std::time::Instant;
use crate::stream::Protocol;

/// 请求体
#[derive(Clone, Debug)]
pub struct Request {
    pub config: Config,
    /// 协议版本
    pub protocol: Protocol,
    /// 当前请求类型
    pub method: Method,
    /// 资源标识符
    pub uri: Uri,
    /// header信息
    pub header: JsonValue,
    /// Cookie信息
    pub cookie: JsonValue,
    /// 请求体
    pub body: Body,
    /// 认证信息
    pub authorization: Authorization,
    /// 处理耗时 ms 毫秒
    pub handle_time: f64,
    /// 请求时间
    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 raw_data: Vec<u8>,
    /// 是否资源
    pub is_resource: bool,
}
impl Request {
    #[must_use]
    pub fn default(config: Config, start_time: Instant) -> Self {
        Self {
            config,
            protocol: Protocol::None,
            method: Method::None,
            uri: Uri::default(),
            header: object! {},
            cookie: object! {},
            body: Body::default(),
            authorization: Authorization::None,
            handle_time: 0.0,
            start_time,
            datetime: String::new(),
            timestamp: 0,
            client_ip: String::new(),
            proxy_ip: String::new(),
            server_ip: String::new(),
            upgrade: Upgrade::Http,
            connection: Connection::None,
            accept_encoding: Encoding::None,
            raw_data: vec![],
            is_resource: false,
        }
    }

    /// 获取请求行信息
    pub fn get_request_line(&mut self, line: &str) -> Result<(), Error> {
        let lines = line.split_whitespace().collect::<Vec<&str>>();
        if lines.len() != 3 {
            return Err(Error::other("请求行错误"));
        }
        self.method = Method::from(lines[0]);
        self.uri = Uri::from(lines[1]);
        self.protocol = Protocol::from(lines[2]);
        Ok(())
    }
    pub fn set_request_line(&mut self, line: &str, bytes: &mut Vec<u8>) -> Result<(), Error> {
        let lines = line.split_whitespace().collect::<Vec<&str>>();
        if lines.len() != 3 {
            return Err(Error::other("请求行错误"));
        }
        self.protocol = Protocol::from(lines[2]);
        match self.protocol {
            Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
                self.method = Method::from(lines[0]);
                self.uri = Uri::from(lines[1]);
            }
            Protocol::HTTP2 => {
                let res = bytes.drain(..8).collect::<Vec<u8>>();
                if !res.eq(b"\r\nSM\r\n\r\n") {
                    return Err(Error::other("HTTP2格式错误"));
                }
            }
            Protocol::None => {}
        }
        Ok(())
    }

    pub fn handle(&mut self, server_ip: &str, client_ip: &str) {
        self.server_ip = server_ip.to_string();
        self.client_ip = client_ip.to_string();

        if self.header.has_key("x-forwarded-for") {
            self.proxy_ip = self.header["x-forwarded-for"].as_str().unwrap_or("").to_string();
        }
        if self.header.has_key("x-real-ip") {
            self.client_ip = self.header["x-real-ip"].as_str().unwrap_or("").to_string();
        }
        self.uri.handle(self.header["host"].as_str().unwrap_or(""));
        self.uri.scheme = if self.config.https { "https" } else { "http" }.to_string();

        let local: DateTime<Local> = Local::now();
        self.datetime = local.format("%Y-%m-%d %H:%M:%S").to_string();
        self.timestamp = local.timestamp();

        self.handle_time = self.start_time.elapsed().as_secs_f64() * 1000.0;

        if self.config.debug {
            info!("响应时间: {}", self.handle_time);
        }
    }
    /// Header处理
    pub fn set_headers(&mut self, data: Lines) {
        let text = unsafe { String::from_utf8_unchecked(self.raw_data.clone()) };
        if self.config.debug {
            info!("\r\n=================请求信息=================\r\n{text}\r\n========================================");
        }
        let mut header = object! {};
        let mut cookie = object! {};
        let mut body = Body::default();

        for text in data {
            let (key, value) = match text.trim().find(':') {
                None => continue,
                Some(e) => {
                    let key = text[..e].trim().to_lowercase().clone();
                    let value = text[e + 1..].trim().to_string();
                    (key, value)
                }
            };
            match key.as_str() {
                "content-type" => match value {
                    _ if value.contains("multipart/form-data") => {
                        let boundarys = value.split("boundary=").collect::<Vec<&str>>();
                        body.boundary = boundarys[1..].join("");
                        body.content_type = ContentType::from("multipart/form-data");
                        let _ = header.insert(key.as_str(), "multipart/form-data");
                    }
                    _ => {
                        let value = match value.find(';') {
                            None => value,
                            Some(e) => value[..e].trim().to_string(),
                        };
                        body.content_type = ContentType::from(value.as_str());
                        let _ = header.insert(key.as_str(), body.content_type.str());
                    }
                },
                "content-length" => {
                    body.content_length = value.to_string().parse::<usize>().unwrap_or(0);
                }
                "authorization" => {
                    self.authorization = Authorization::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 _ = cookie.insert(key.as_str(), val);
                            }
                        }
                        ""
                    }).collect::<Vec<&str>>();
                }
                "upgrade" => {
                    self.upgrade = Upgrade::from(&value);
                }
                "connection" => {
                    self.connection = Connection::from(&value);
                }
                "accept-encoding" => {
                    self.accept_encoding = Encoding::from(&value);
                }
                _ => {
                    let _ = header.insert(key.as_str(), value);
                }
            }
        }
        self.header = header.clone();
        self.cookie = cookie.clone();
        self.body = body.clone();
    }
    pub fn set_http2_headers(&mut self, key: &str, value: &str) {
        match key {
            "content-type" => match value {
                _ if value.contains("multipart/form-data") => {
                    let boundarys = value.split("boundary=").collect::<Vec<&str>>();
                    self.body.boundary = boundarys[1..].join("");
                    self.body.content_type = ContentType::from("multipart/form-data");
                    self.header.insert(key, "multipart/form-data").unwrap();
                }
                _ => {
                    let value = match value.find(';') {
                        None => value,
                        Some(e) => &*value[..e].trim().to_string(),
                    };
                    self.body.content_type = ContentType::from(value);
                    let _ = self.header.insert(key, self.body.content_type.str());
                }
            },
            "content-length" => {
                self.body.content_length = value.to_string().parse::<usize>().unwrap_or(0);
            }
            "authorization" => {
                self.authorization = Authorization::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>>();
            }
            "upgrade" => {
                self.upgrade = Upgrade::from(value);
            }
            "connection" => {
                self.connection = Connection::from(value);
            }
            "accept-encoding" => {
                self.accept_encoding = Encoding::from(value);
            }
            _ => {
                self.header.insert(key, value).unwrap();
            }
        }
    }

    /// 保存日志
    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: {:?} ms\r\n",
            self.datetime,
            self.protocol.str(),
            self.client_ip,
            self.method.str(),
            self.uri.url,
            self.body.content_length,
            self.body.content_type.str(),
            self.handle_time
        );
        file.write_all(data.as_bytes())?;
        Ok(())
    }
    /// 读取资源文件
    pub fn read_resource(&mut self) -> io::Result<PathBuf> {
        if self.uri.path != "/" {
            let file = self.config.root_path.join(self.config.public.clone()).join(self.uri.path.trim_start_matches('/'));
            if file.is_file() {
                return Ok(file);
            }
        }
        if let Method::GET = self.method {
            if self.uri.path == "/" {
                let file = self.config.root_path.join("webpage").join(self.config.webpage.clone()).join("index.html");
                if file.is_file() {
                    return Ok(file);
                }
            } else {
                let file = self.config.root_path.join("webpage").join(self.config.webpage.clone()).join(self.uri.path.trim_start_matches('/'));
                if file.is_file() {
                    return Ok(file);
                }
            }
        }
        Err(Error::other("Not a file"))
    }
}


/// 请求方法
#[derive(Clone, Debug)]
pub enum Method {
    POST,
    GET,
    HEAD,
    PUT,
    DELETE,
    OPTIONS,
    PATCH,
    TRACE,
    VIEW,
    PROPFIND,
    /// http2.0
    PRI,
    None,
}

impl Method {
    #[must_use]
    pub fn from(name: &str) -> Self {
        match name.to_lowercase().as_str() {
            "post" => Self::POST,
            "get" => Self::GET,
            "head" => Self::HEAD,
            "put" => Self::PUT,
            "delete" => Self::DELETE,
            "options" => Self::OPTIONS,
            "patch" => Self::PATCH,
            "trace" => Self::TRACE,
            "view" => Self::VIEW,
            "propfind" => Self::PROPFIND,
            "pri" => Self::PRI,
            _ => Self::None,
        }
    }
    pub fn str(&mut self) -> &str {
        match self {
            Method::POST => "POST",
            Method::GET => "GET",
            Method::HEAD => "HEAD",
            Method::PUT => "PUT",
            Method::DELETE => "DELETE",
            Method::OPTIONS => "OPTIONS",
            Method::PATCH => "PATCH",
            Method::TRACE => "TRACE",
            Method::VIEW => "VIEW",
            Method::PROPFIND => "PROPFIND",
            Method::PRI => "PRI",
            Method::None => "",
        }
    }
}
/// 统一资源标识符
#[derive(Clone, Debug)]
pub struct Uri {
    /// 完整 url
    pub url: String,
    /// 查询字符串
    pub query: String,
    /// 查询参数
    pub query_params: JsonValue,
    /// 片段或位置
    pub fragment: String,
    /// 资源路径
    pub path: String,
    /// 资源段落
    pub path_segments: Vec<String>,
    /// 访问协议
    pub scheme: String,
    /// 主机名或 IP 地址
    pub host: String,
    /// 端口号
    pub port: String,
}
impl Uri {
    #[must_use]
    pub fn from(url: &str) -> Self {
        let mut decoded_url = Uri::decode(url).unwrap_or(url.to_string());
        let fragment = match decoded_url.rfind('#') {
            None => String::new(),
            Some(index) => decoded_url.drain(index..).collect::<String>(),
        };
        let mut query = String::new();
        let query_params = match decoded_url.rfind('?') {
            None => object! {},
            Some(index) => {
                let text = decoded_url.drain(index..).collect::<String>();
                query = text.trim_start_matches('?').parse().unwrap();
                let text = query.split('&').collect::<Vec<&str>>();
                let mut params = object! {};
                for &item in &text {
                    if let Some(index) = item.find('=') {
                        let key = item[..index].to_string();
                        let value = item[index + 1..].to_string();
                        let _ = params.insert(
                            Uri::decode(&key).unwrap_or(key.to_string()).as_str(),
                            Uri::decode(&value).unwrap_or(key.to_string()),
                        );
                    }
                }
                params
            }
        };
        let path_segments = decoded_url.split('/').collect::<Vec<&str>>();
        let path_segments = path_segments.into_iter().filter(|&x| !x.is_empty()).collect::<Vec<&str>>().iter().map(|&x| x.to_string()).collect::<Vec<String>>();
        Self {
            url: url.to_string(),
            query,
            query_params,
            fragment,
            path: decoded_url.clone(),
            path_segments,
            scheme: String::new(),
            host: String::new(),
            port: String::new(),
        }
    }
    /// 解码
    pub fn decode(input: &str) -> Result<String, String> {
        let mut decoded = String::new();
        let bytes = input.as_bytes();
        let mut i = 0;

        while i < bytes.len() {
            if bytes[i] == b'%' {
                if i + 2 >= bytes.len() {
                    return Err("Incomplete percent-encoding".into());
                }
                let hex = &input[i + 1..i + 3];
                match u8::from_str_radix(hex, 16) {
                    Ok(byte) => decoded.push(byte as char),
                    Err(_) => return Err(format!("Invalid percent-encoding: %{hex}")),
                }
                i += 3;
            } else if bytes[i] == b'+' {
                decoded.push(' ');
                i += 1;
            } else {
                decoded.push(bytes[i] as char);
                i += 1;
            }
        }

        Ok(decoded)
    }
    pub fn handle(&mut self, host: &str) {
        if !host.is_empty() {
            let hostport = host.split(':').collect::<Vec<&str>>();
            if hostport.len() > 1 {
                self.host = hostport[0].to_string();
                self.port = hostport[1].to_string();
            } else {
                self.host = hostport[0].to_string();
            }
        }
    }
    #[must_use]
    pub fn to_json(&self) -> JsonValue {
        object! {
            url: self.url.clone(),
            query: self.query.clone(),
            query_params: self.query_params.clone(),
            fragment: self.fragment.clone(),
            path: self.path.clone(),
            path_segments: self.path_segments.clone(),
            scheme: self.scheme.clone(),
            host: self.host.clone(),
            port: self.port.clone(),
        }
    }
}

impl Default for Uri {
    fn default() -> Self {
        Self {
            url: String::new(),
            query: String::new(),
            query_params: object! {},
            fragment: String::new(),
            path: String::new(),
            scheme: String::new(),
            path_segments: Vec::new(),
            host: String::new(),
            port: String::new(),
        }
    }
}

/// 内容类型
#[derive(Debug, Clone)]
pub enum ContentType {
    FormData,
    FormUrlencoded,
    Json,
    Xml,
    Javascript,
    Text,
    Html,
    Other(String),
}
impl ContentType {
    #[must_use]
    pub fn from(name: &str) -> Self {
        match name {
            "multipart/form-data" => Self::FormData,
            "application/x-www-form-urlencoded" => Self::FormUrlencoded,
            "application/json" => Self::Json,
            "application/xml" | "text/xml" => Self::Xml,
            "application/javascript" => Self::Javascript,
            "text/html" => Self::Html,
            "text/plain" => Self::Text,
            _ => Self::Other(name.to_string()),
        }
    }
    pub fn str(&mut self) -> String {
        match self {
            Self::FormData => "multipart/form-data",
            Self::FormUrlencoded => "application/x-www-form-urlencoded",
            Self::Json => "application/json",
            Self::Xml => "application/xml",
            Self::Javascript => "application/javascript",
            Self::Text => "text/plain",
            Self::Html => "text/html",
            Self::Other(name) => name,
        }.to_string()
    }
}
/// 认证
#[derive(Clone, Debug)]
pub enum Authorization {
    Basic(String, String),
    Bearer(String),
    Digest(JsonValue),
    None,
}
impl Authorization {
    #[must_use]
    pub fn from(data: &str) -> Self {
        let authorization = data.split_whitespace().collect::<Vec<&str>>();
        let mode = authorization[0].to_lowercase();
        match mode.as_str() {
            "basic" => match decode(&authorization[1].to_string().clone()) {
                Ok(decoded) => {
                    let text = String::from_utf8(decoded.clone()).unwrap();
                    let text: Vec<&str> = text.split(':').collect();
                    Self::Basic(text[0].to_string(), text[1].to_string())
                }
                Err(e) => {
                    error!("{}basic认证解码错误: {}", line!(), e);
                    Self::Basic(String::new(), String::new())
                }
            },
            "bearer" => Self::Bearer(authorization[1].to_string()),
            "digest" => {
                let text = authorization[1..].concat().clone();
                let text = text.split(',').collect::<Vec<&str>>();
                let mut params = object! {};
                for item in &text {
                    let index = match item.find('=') {
                        None => continue,
                        Some(e) => e,
                    };
                    let key = item[..index].to_string();
                    let value = item[index + 2..item.len() - 1].to_string();
                    let _ = params.insert(key.as_str(), value);
                }

                Self::Digest(params)
            }
            _ => {
                warn!("未知认证模式: {mode}");
                Self::None
            }
        }
    }
    pub fn str(&mut self) -> JsonValue {
        match self {
            Authorization::Basic(key, value) => {
                let mut data = object! {};
                data[key.as_str()] = value.clone().into();
                data
            }
            Authorization::Bearer(e) => e.clone().into(),
            Authorization::Digest(e) => e.clone(),
            Authorization::None => "".into(),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Body {
    pub content_type: ContentType,
    pub boundary: String,
    pub content_length: usize,
    pub content: JsonValue,
}
impl Body {
    pub fn set_content(&mut self, data: Vec<u8>) {
        if self.content_length==0{
            return;
        }
        match self.content_type.clone() {
            ContentType::FormData => {
                let mut fields = object! {};
                let boundary_marker = format!("--{}", self.boundary);


                let parts = split_vec_u8(&data, boundary_marker.as_bytes());

                for part in parts {
                    if part.eq(b"\r\n") || part.is_empty() || part.eq(b"--") || part.eq(b"--\r\n") || part.eq(format!("--{}", self.boundary).as_bytes()) {
                        continue; // 跳过无效部分
                    }

                    let headers_and_body = split_vec_u8(&part, b"\r\n\r\n");
                    if headers_and_body.len() == 1 {
                        let headers = unsafe { String::from_utf8_unchecked(headers_and_body[0].clone()) };
                        error!(">>>>>>>>>>>>{headers:?}");
                        continue;
                    }

                    let headers = unsafe { String::from_utf8_unchecked(headers_and_body[0].clone()) };
                    let body = headers_and_body[1].clone();
                    {
                        // 解析头部，查找 Content-Disposition
                        let headers = headers.split("\r\n");

                        let mut field_name = "";
                        let mut filename = "";
                        let mut content_type = ContentType::Text;

                        for header in headers {
                            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);
                            fields[field_name.to_string()] = JsonValue::from(text.lines().next().unwrap());
                        } else {
                            let extension = Path::new(filename).extension() // 可能返回 None
                                                               .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:sha_256(body.clone()),
                                        name:filename,
                                        suffix:suffix,
                                        size:body.len(),
                                        type:content_type.str(),
                                        file:temp_dir.to_str()
                                    }).unwrap();
                            }
                        }
                    }
                }
                self.content = fields;
            }
            ContentType::FormUrlencoded => {
                let text = unsafe { String::from_utf8_unchecked(data) };
                let params = text.split('&').collect::<Vec<&str>>();
                let mut list = object! {};
                for param in &params {
                    let t = param.split('=').collect::<Vec<&str>>().iter().map(|&x| Uri::decode(x).unwrap_or(x.to_string())).collect::<Vec<String>>();
                    list[t[0].to_string()] = t[1].clone().into();
                }
                self.content = list;
            }
            ContentType::Json => {
                let text = unsafe { String::from_utf8_unchecked(data) };
                self.content = json::parse(text.as_str()).unwrap_or(object! {});
            }
            ContentType::Xml | ContentType::Html | ContentType::Text | ContentType::Javascript | ContentType::Other(_) => {
                let text = unsafe { String::from_utf8_unchecked(data) };
                self.content = text.into();
            }
        }
    }
}
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
}
impl Default for Body {
    fn default() -> Self {
        Self {
            content_type: ContentType::Other("text/plain".to_string()),
            boundary: String::new(),
            content_length: 0,
            content: object! {},
        }
    }
}
/// 消息内容
#[derive(Clone, Debug)]
pub enum Content {
    FormUrlencoded(JsonValue),
    FormData(JsonValue),
    Json(JsonValue),
    Text(JsonValue),
    Xml(JsonValue),
    None,
}
impl Content {}
#[derive(Clone, Debug)]
pub enum FormData {
    File(String, PathBuf),
    Field(JsonValue),
}

#[derive(Clone, Debug)]
pub enum Upgrade {
    Websocket,
    Http,
    None,
}
impl Upgrade {
    #[must_use]
    pub fn from(name: &str) -> Self {
        match name.to_lowercase().as_str() {
            "websocket" => Self::Websocket,
            "http" => Self::Http,
            _ => Self::None,
        }
    }
    pub fn str(&mut self) -> String {
        match self {
            Self::Websocket => "websocket",
            Self::Http => "http",
            Self::None => "",
        }.to_string()
    }
}

#[derive(Clone, Debug)]
pub enum Connection {
    KeepAlive,
    Close,
    Upgrade,
    None,
}
impl Connection {
    #[must_use]
    pub fn from(value: &str) -> Self {
        match value.to_lowercase().as_str() {
            "upgrade" => Self::Upgrade,
            "keep-alive" => Self::KeepAlive,
            "close" => Self::Close,
            _ => Self::None,
        }
    }
}
