mod stream;
pub mod config;
pub mod request;
pub mod response;
pub mod websocket;
#[cfg(feature = "pools")]
mod pools;
use crate::stream::{Scheme};
use crate::config::{Config};
use crate::request::{Request};
use crate::response::Response;
use crate::websocket::{CloseCode, ErrorCode, Message, Websocket};
use log::{error, info, warn};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use std::io::{BufReader, Error, Write};
use std::net::{TcpListener};
use std::sync::{Arc, Mutex};
use std::time::{Duration};
use std::{io, thread};
use std::fmt::Debug;
use std::path::PathBuf;
use flate2::Compression;
use flate2::write::GzEncoder;
use json::{object, JsonValue};

/// 网络服务
#[derive(Clone, Debug)]
pub struct WebServer;

impl WebServer {
    /// 后台服务器
    pub fn new_service(config: Config, factory: fn(out: Websocket) -> Box<dyn Handler>) {
        loop {
            match WebServer::service(config.clone(), factory) {
                Ok(()) => {}
                Err(e) => error!("服务器错误: {}[{}]: {}", file!(), line!(), e),
            }
            warn!("服务器 1秒后重启");
            thread::sleep(Duration::from_secs(1));
        }
    }
    fn service(config: Config, factory: fn(out: Websocket) -> Box<dyn Handler>) -> io::Result<()> {
        info!("==================== 网络服务 服务信息 ====================");
        info!("日志记录: {}",if config.log {"开启"} else {"关闭"});
        info!("调试模式: {}",if config.debug { "开启" } else { "关闭" });
        info!("监听地址: {}", config.host);
        info!("服务地址: {}://{}",if config.https { "https" } else { "http" },config.host);
        info!("根 目 录: {}", config.root_path.to_str().unwrap());
        info!("访问目录: {}", config.public);
        info!("运行目录: {}", config.runtime);
        info!("SSL/TLS: {}",if config.https { "开启" } else { "关闭" });

        if config.https {
            info!("证书目录KEY: {:?}", config.tls.key);
            info!("证书目录PEM: {:?}", config.tls.certs);
        }

        let listener = TcpListener::bind(config.host.clone())?;
        info!("==================== 网络服务 启动成功 ====================");

        let acceptor = Self::ssl(config.clone())?;
        #[cfg(feature = "pools")] let mut pool = pools::Pool::new(config.pools_max * 4);
        for stream in listener.incoming() {
            match stream {
                Ok(stream) => {
                    let config_new = config.clone();
                    let acceptor_new = acceptor.clone();
                    #[cfg(not(feature = "pools"))]
                    thread::spawn(move || {
                        stream.set_nonblocking(false).unwrap();
                        // 设置读取超时时间
                        stream.set_read_timeout(Some(Duration::from_secs(15))).unwrap_or_default();
                        // 设置发送超时时间
                        stream.set_write_timeout(Some(Duration::from_secs(15))).unwrap_or_default();

                        let scheme = if config_new.https {
                            match acceptor_new.accept(stream) {
                                Ok(e) => Scheme::Https(Arc::new(Mutex::new(BufReader::new(e)))),
                                Err(_) => return Err(Error::other("加载加密请求失败")),
                            }
                        } else {
                            Scheme::Http(Arc::new(Mutex::new(BufReader::new(stream))))
                        };

                        let mut request = Request::new(config_new.clone(), Arc::new(Mutex::new(scheme.clone())));
                        let response = match request.handle() {
                            Ok(()) => Response::new(request.clone(), factory),
                            Err(e) => {
                                error!("处理请求: {:?} {} {}",thread::current().id() ,e.code, e.body);
                                return Err(Error::other(e.body.as_str()));
                            }
                        };
                        match response.handle() {
                            Ok(()) => {}
                            Err(e) => {
                                error!("发送错误失败2: {}",e.to_string());
                                return Err(Error::other(e));
                            }
                        };
                        match request.save_log() {
                            Ok(()) => {}
                            Err(_) => error!("日志记录错误")
                        }
                        Ok(())
                    });

                    #[cfg(feature = "pools")]
                    pool.execute(move || -> io::Result<()> {

                        // 设置读取超时时间
                        stream.set_read_timeout(Some(Duration::from_secs(15))).unwrap_or_default();
                        // 设置发送超时时间
                        stream.set_write_timeout(Some(Duration::from_secs(15))).unwrap_or_default();


                        let scheme = if config_new.https {
                            match acceptor_new.accept(stream) {
                                Ok(e) => Scheme::Https(Arc::new(Mutex::new(BufReader::new(e)))),
                                Err(_) => return Err(Error::other("加载加密请求失败")),
                            }
                        } else {
                            Scheme::Http(Arc::new(Mutex::new(BufReader::new(stream))))
                        };
                        let mut request = Request::new(config_new.clone(), Arc::new(Mutex::new(scheme.clone())));
                        let request_req = request.handle();
                        let mut response = Response::new(request.clone(), factory);
                        match request_req {
                            Ok(()) => {}
                            Err(e) => return match response.status(e.code).txt(e.body.as_str()).send() {
                                Ok(()) => Ok(()),
                                Err(e) => Err(Error::other(e.body.as_str())),
                            }
                        };
                        response.handle()?;
                        match request.save_log() {
                            Ok(()) => {}
                            Err(_) => {
                                error!("日志记录错误");
                            }
                        }
                        Ok(())
                    });
                }
                Err(e) => return Err(e),
            }
        }
        #[cfg(feature = "pools")]
        pool.end();
        Ok(())
    }

    fn ssl(config: Config) -> io::Result<Arc<SslAcceptor>> {
        if config.https {
            let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
            if !config.tls.key.is_file() {
                return Err(Error::other(
                    format!("private.key 不存在: {:?}", config.tls.key).as_str(),
                ));
            }
            if !config.tls.certs.is_file() {
                return Err(Error::other(
                    format!("certificate.pem 不存在: {:?}", config.tls.certs).as_str(),
                ));
            }
            acceptor.set_private_key_file(config.tls.key.clone(), SslFiletype::PEM)?;
            acceptor.set_certificate_file(config.tls.certs.clone(), SslFiletype::PEM)?;
            Ok(Arc::new(acceptor.build()))
        } else {
            Ok(Arc::new(SslAcceptor::mozilla_intermediate(SslMethod::tls())?.build()))
        }
    }
}

pub trait HandlerClone {
    fn clone_box(&self) -> Box<dyn Handler>;
}

/// 实现 HandlerClone for 所有 Handler + Clone 的实现者
impl<T> HandlerClone for T
where
    T: 'static + Handler + Clone,
{
    fn clone_box(&self) -> Box<dyn Handler> {
        Box::new(self.clone())
    }
}

// 为 dyn Handler 实现 Clone
impl Clone for Box<dyn Handler> {
    fn clone(&self) -> Box<dyn Handler> {
        self.clone_box()
    }
}
pub trait Handler: Send + Sync + HandlerClone + Debug {
    /// 请求 处理
    fn on_request(&mut self, _request: Request, _response: &mut Response);
    /// 预检请求处理 OPTIONS
    fn on_options(&mut self, response: &mut Response) {
        response.allow_origins = vec![];
        response.allow_methods = vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"];
        response.allow_headers = vec!["Authorization", "X-Forwarded-For", "X-Real-IP"];
        response.header("Access-Control-Expose-Headers", "Content-Disposition");
        response.header("Access-Control-Max-Age", 86400.to_string().as_str());
    }
    /// 响应 处理
    fn on_response(&mut self, response: &mut Response) {
        if !response.headers.has_key("Access-Control-Allow-Origin") {
            response.header("Access-Control-Allow-Origin", "*");
        }
        // 允许前端跨域请求时发送和接收 cookie / 凭据
        if !response.headers.has_key("Access-Control-Allow-Credentials") {
            response.header("Access-Control-Allow-Credentials", "true");
        }
        // 允许前端读取指定请求头
        if !response.headers.has_key("Access-Control-Expose-Headers") {
            response.header("Access-Control-Expose-Headers", "Content-Disposition");
        }
    }

    fn on_frame(&mut self) -> Result<(), HttpError> {
        Ok(())
    }
    /// 握手监听
    fn on_open(&mut self) -> Result<(), HttpError> {
        Ok(())
    }
    /// 接收到消息
    fn on_message(&mut self, _msg: Message) -> Result<(), HttpError> {
        Ok(())
    }
    /// 关闭监听
    fn on_close(&mut self, _code: CloseCode, _reason: &str) {}
    /// 错误监听
    fn on_error(&mut self, _err: ErrorCode) {}
    /// 关机监听
    fn on_shutdown(&mut self) {}
}


#[derive(Clone, Debug)]
pub enum Connection {
    /// 长连接
    KeepAlive,
    /// 短连接
    Close,
    Other(String),
}
impl Connection {
    fn from(value: &str) -> Self {
        match value.to_lowercase().as_str() {
            "keep-alive" => Self::KeepAlive,
            "close" => Self::Close,
            _ => Self::Other(value.to_string()),
        }
    }
    pub fn str(&self) -> &str {
        match self {
            Connection::KeepAlive => "keep-alive",
            Connection::Close => "close",
            Connection::Other(name) => name
        }
    }
}
#[derive(Clone, Debug)]
pub enum Upgrade {
    Websocket,
    Http,
    Other(String),
}
impl Upgrade {
    fn from(name: &str) -> Self {
        match name.to_lowercase().as_str() {
            "websocket" => Self::Websocket,
            "http" => Self::Http,
            _ => Self::Other(name.to_lowercase().as_str().to_string()),
        }
    }
    pub fn str(&self) -> &str {
        match self {
            Self::Websocket => "websocket",
            Self::Http => "http",
            Self::Other(name) => name,
        }
    }
}

/// 统一资源标识符
#[derive(Clone, Debug)]
#[derive(Default)]
pub struct Uri {
    /// 资源标识
    pub uri: String,
    /// 完整 url
    pub url: String,
    /// 查询字符串
    pub query: String,
    /// 片段或位置
    pub fragment: String,
    /// 资源路径
    pub path: String,
    /// 资源段落
    pub path_segments: Vec<String>,
}
impl Uri {
    pub fn from(url: &str) -> Self {
        let mut decoded_url = br_crypto::encoding::urlencoding_decode(url);
        let fragment = match decoded_url.rfind('#') {
            None => String::new(),
            Some(index) => decoded_url.drain(index..).collect::<String>(),
        };

        let query = match decoded_url.rfind('?') {
            None => String::new(),
            Some(index) => decoded_url.drain(index..).collect::<String>().trim_start_matches("?").to_string(),
        };

        let path_segments = decoded_url.split("/").map(|x| x.to_string()).filter(|x| !x.is_empty()).collect::<Vec<String>>();
        Self {
            uri: decoded_url.clone(),
            url: url.to_string(),
            query,
            fragment,
            path: decoded_url.clone(),
            path_segments,
        }
    }
    /// 获取请求参数
    pub fn get_query_params(&self) -> JsonValue {
        let text = self.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(key.as_str(), value);
            }
        }
        params
    }
    #[must_use]
    pub fn to_json(&self) -> JsonValue {
        object! {
            url: self.url.clone(),
            query: self.query.clone(),
            fragment: self.fragment.clone(),
            path: self.path.clone(),
            path_segments: self.path_segments.clone()
        }
    }
}


/// 请求方法
#[derive(Clone, Debug)]
pub enum Method {
    /// 请求
    POST,
    /// 获取
    GET,
    /// 请求头
    HEAD,
    /// 更新
    PUT,
    /// 删除
    DELETE,
    /// 预请求
    OPTIONS,
    PATCH,
    TRACE,
    VIEW,
    CONNECT,
    PROPFIND,
    /// http2.0
    PRI,
    /// 其他
    Other(String),
}

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,
            "connect" => Self::CONNECT,
            "pri" => Self::PRI,
            _ => Self::Other(name.to_string()),
        }
    }
    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::CONNECT => "CONNECT",
            Method::Other(e) => e
        }
    }
}

#[derive(Debug, Clone)]
pub struct HttpError {
    pub code: u16,
    pub body: String,
}

impl HttpError {
    /// 构造函数：用状态码和文本信息
    pub fn new(code: u16, body: &str) -> Self {
        Self {
            code,
            body: body.to_string(),
        }
    }
}
/// 内容类型
#[derive(Debug, Clone)]
pub enum ContentType {
    FormData,
    FormUrlencoded,
    Json,
    Xml,
    Javascript,
    Text,
    Html,
    Stream,
    Other(String),
}
impl ContentType {
    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,
            "application/octet-stream" => Self::Stream,
            "text/html" => Self::Html,
            "text/plain" => Self::Text,
            _ => Self::Other(name.to_string()),
        }
    }
    pub fn str(&self) -> &str {
        match self {
            ContentType::FormData => "multipart/form-data",
            ContentType::FormUrlencoded => "application/x-www-form-urlencoded",
            ContentType::Json => "application/json",
            ContentType::Xml => "application/xml",
            ContentType::Javascript => "application/javascript",
            ContentType::Text => "text/plain",
            ContentType::Html => "text/html",
            ContentType::Other(name) => name.as_str(),
            ContentType::Stream => "application/octet-stream"
        }
    }
}
/// 认证
#[derive(Clone, Debug)]
pub enum Authorization {
    Basic(String, String),
    Bearer(String),
    Digest(JsonValue),
    Other(String),
}
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" => {
                let text = br_crypto::base64::decode(&authorization[1].to_string().clone());
                let text: Vec<&str> = text.split(':').collect();
                Self::Basic(text[0].to_string(), text[1].to_string())
            }
            "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 Some(index) = item.find('=') else { continue };
                    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)
            }
            _ => Self::Other(data.to_string())
        }
    }
    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::Other(name) => name.clone().into(),
        }
    }
}
/// 消息内容
#[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 Language {
    ZhCN,
    ZhHans,
    En,
    Other(String),

}
impl Language {
    #[must_use]
    pub fn from(name: &str) -> Self {
        let binding = name.split(',').collect::<Vec<&str>>()[0].trim().to_lowercase();
        let name = binding.as_str();
        match name {
            "zh-cn" => Self::ZhCN,
            "zh-hans" => Self::ZhHans,
            "en" => Self::En,
            _ => Self::Other(name.to_string()),
        }
    }
    #[must_use]
    pub fn str(&self) -> &str {
        match self {
            Language::ZhCN => "zh-CN",
            Language::ZhHans => "zh-Hans",
            Language::En => "en",
            Language::Other(e) => e.as_str(),
        }
    }
}


/// 压缩方式
#[derive(Clone, Debug)]
pub enum Encoding {
    Gzip,
    Deflate,
    Br,
    Bzip2,
    None,
}
impl Encoding {
    #[must_use]
    pub fn from(s: &str) -> Encoding {
        match s.to_lowercase().as_str() {
            x if x.contains("gzip") => Encoding::Gzip,
            x if x.contains("deflate") => Encoding::Deflate,
            x if x.contains("br") => Encoding::Br,
            x if x.contains("bzip2") => Encoding::Bzip2,
            _ => Encoding::None,
        }
    }
    #[must_use]
    pub fn str(&self) -> &str {
        match self {
            Encoding::Gzip => "gzip",
            Encoding::Deflate => "deflate",
            Encoding::Br => "br",
            Encoding::None => "",
            Encoding::Bzip2 => "bzip2",
        }
    }
    pub fn compress(self, data: &[u8]) -> io::Result<Vec<u8>> {
        match self {
            Encoding::Gzip => {
                let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
                encoder.write_all(data)?;
                encoder.finish()
            }
            _ => Ok(data.to_vec()),
        }
    }
}
