use std::{fs, thread};
use std::net::TcpListener;
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;
use json::{JsonValue};
use log::{error, info};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use crate::config::Config;
use crate::request::{Method, Request};
use crate::response::Response;
use std::process::Command;

/// 配置
mod config;
/// 服务接收
mod service;
mod stream;
pub mod request;
pub mod response;
pub mod content_type;

#[derive(Debug, Clone)]
pub struct Web {
    pub config: Config,
}

impl Web {
    pub fn new(path: &str) -> Self {
        let config = match fs::read_to_string(path) {
            Ok(content) => {
                match json::parse(content.as_str()) {
                    Ok(e) => e,
                    Err(_) => {
                        let res = Config::default();
                        let json = res.json();
                        fs::write(path, json.to_string()).unwrap();
                        json
                    }
                }
            }
            Err(_) => {
                let res = Config::default();
                let json = res.json();
                fs::write(path, json.to_string()).unwrap();
                json
            }
        };
        let mut config = Config::from(config);

        // 根据不同的操作系统选择合适的命令
        let command_output = if cfg!(target_os = "windows") {
            Command::new("ipconfig")
                .args(&["|", "findstr", "IPv4"])
                .output()
        } else if cfg!(target_os = "macos") {
            Command::new("ipconfig").arg("getifaddr").arg("en0").output()
        } else {
            Command::new("sh")
                .arg("-c")
                .arg("ip addr show")
                .output()
        };
        let ip = match command_output {
            Ok(e) => {
                let output_str = String::from_utf8_lossy(&e.stdout);
                output_str.trim().to_string()
            }
            Err(_) => {
                "127.0.0.1".to_string()
            }
        };

        info!("==================== Web Service ====================");
        info!("[addr]  服务器地址: {}:{}",config.host,config.port);
        info!("[domain]     域名: {}", config.domain);
        info!("[public]  公共目录: {}", config.public);
        info!("[runtime] 运行目录: {}", config.runtime);
        info!("[ssl]     开启状态: {}", config.ssl);

        config.url = if config.ssl {
            info!("[pkey]       私钥: {}", config.ssl_pkey.clone());
            info!("[certs]      证书: {}", config.ssl_certs.clone());
            format!("https://{}:{}", ip, config.port)
        } else {
            format!("http://{}:{}", ip, config.port)
        };
        Self {
            config: config.clone()
        }
    }
    /// 获取本机真实IP
    pub fn service(&mut self, factory: fn() -> Box<dyn Handler>) {
        loop {
            let listener = match TcpListener::bind(format!("{}:{}", self.config.host.clone(), self.config.port.clone()).as_str()) {
                Ok(listener) => listener,
                Err(e) => {
                    error!("监听失败: {}", e.to_string());
                    error!("服务器断线5秒后重启");
                    thread::sleep(Duration::from_secs(5));
                    continue;
                }
            };
            info!("====================启动 {} 成功====================",self.config.url);

            let ssl = match self.ssl() {
                Ok(e) => e,
                Err(_) => {
                    error!("加密失败 服务器断线5秒后重启");
                    thread::sleep(Duration::from_secs(5));
                    continue;
                }
            };

            for stream in listener.incoming() {
                let stream = stream.unwrap();
                let config = self.config.clone();
                let ssl = ssl.clone();
                let factory = factory.clone();
                thread::spawn(move || {
                    match service::Service::new(stream.try_clone().unwrap(), config.clone(), ssl.clone()) {
                        Ok(mut service) => {
                            let request = match service.request_header() {
                                Ok(e) => e,
                                Err(e) => {
                                    return error!("请求头部错误: {}",e);
                                }
                            };
                            let mut req = Request::new(config.clone(), request.clone());
                            req.server_ip = stream.local_addr().unwrap().ip().to_string();
                            req.client_ip = stream.peer_addr().unwrap().ip().to_string();
                            req.header();
                            if !req.is_origin {
                                return;
                            }
                            if req.content_length > 0 {
                                let request = match service.request_body(req.content_length) {
                                    Ok(e) => e,
                                    Err(e) => {
                                        return error!("请求错误: {}",e);
                                    }
                                };
                                if config.debug {
                                    info!("接收到的: {:?}",String::from_utf8_lossy(request.as_slice()));
                                }
                                req.body(request.clone());
                            }

                            let mut res = Response::new(config.clone(), req.version.clone());
                            let res_text = match req.method {
                                Method::OPTIONS => {
                                    res.options()
                                }
                                Method::None => {
                                    return error!("错误请求: {:#}",req.json());
                                }
                                _ => {
                                    let file = format!("{}{}", config.public.clone(), req.uri.clone());
                                    let file_info = Path::new(file.as_str());
                                    if file_info.is_file() {
                                        res.file(file.clone())
                                    } else {
                                        let (types, data) = (factory)().on_request(req.clone()).clone();
                                        res.set_content_type(types).receipt(data)
                                    }
                                }
                            };
                            match service.response(res_text.clone()) {
                                Ok(_) => {
                                    if config.debug {
                                        info!("响应OK: {}",res_text);
                                    }
                                }
                                Err(e) => {
                                    error!("发送错误: {}",e.to_string());
                                }
                            }
                        }
                        Err(e) => {
                            error!("请求错误: {}",e);
                        }
                    };
                });
                info!("用户退出");
            }
            error!("服务器断线5秒后重启");
            thread::sleep(Duration::from_secs(5));
        }
    }
    fn ssl(&mut self) -> Result<Arc<SslAcceptor>, String> {
        let res = if self.config.ssl {
            let mut acceptor = match SslAcceptor::mozilla_intermediate(SslMethod::tls()) {
                Ok(e) => e,
                Err(e) => {
                    return Err(format!("{}", e.to_string()));
                }
            };
            match acceptor.set_private_key_file(self.config.ssl_pkey.clone(), SslFiletype::PEM) {
                Ok(_) => {}
                Err(e) => return Err(format!("加载私钥失败: {}", e.to_string()))
            }
            match acceptor.set_certificate_file(self.config.ssl_certs.clone(), SslFiletype::PEM) {
                Ok(_) => {}
                Err(e) => return Err(format!("加载正式失败: {}", e.to_string()))
            }
            Arc::new(acceptor.build())
        } else {
            Arc::new(SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap().build())
        };
        Ok(res)
    }
}

/// 监听事件
pub trait Handler {
    /// 接收到请求
    fn on_request(&mut self, mut req: Request) -> (&'static str, JsonValue) {
        ("json", req.json())
    }
}