#![allow(non_snake_case)]
#![allow(non_camel_case_types)] 
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(dead_code)] 


use local_ip_address::{self,local_ip};
use portpicker;


use std::{
    time
};



//https://gitee.com/mirrors/Salvo

use salvo::{
    prelude::*,
    server::ServerHandle,
};
use async_compat::{Compat, CompatExt};




use lwleen_rpc::serde_json;
use crate::prelude::*;
use super::*;
use super::web_app::*;

pub static 全局_WEB服务器管理: OnceCell<WEB服务器管理> = OnceCell::new(); 




pub struct Builder_WEB服务器{
    信令路由:信令路由,
    协议头: Option<String>,
    ip: Option<String>,
    端口: Option<u16>,
    路由表: Option<HashMap<String,Vec<String>>>,
    立即启动:Option<bool>,
    tls证书:Option<Vec<String>>,
}
impl Builder_WEB服务器{
    pub fn new(信令路由:信令路由) -> Self { Self{ 信令路由,协议头:None,ip:None,端口:None,路由表:None,立即启动:None,tls证书:None }  }
    pub fn 协议头(mut self, 协议头:impl AsRef<str>) -> Self {  self.协议头 = Some(协议头.as_ref().to_string());  self }
    pub fn ip(mut self, ip: impl AsRef<str>) -> Self {  self.ip = Some(ip.as_ref().to_string());  self }
    pub fn 端口(mut self, 端口: u16) -> Self {  self.端口 = Some(端口);  self }
    pub fn 路由表(mut self, 路由表: HashMap<String,Vec<String>>) -> Self {  self.路由表 = Some(路由表);  self }
    pub fn 立即启动(mut self, 立即启动: bool) -> Self {  self.立即启动 = Some(立即启动);  self }
    pub fn tls证书(mut self, tls证书: Vec<String>) -> Self {  self.tls证书 = Some(tls证书);  self }
    pub fn build(self)->impl 信令任务<原子ID>{
        let Self{ 信令路由,协议头,ip,端口,路由表,立即启动, tls证书 } = self;
        core发布信令任务!(信令路由, 信令表::WEB服务器_新建 { 协议头, ip ,端口 ,路由表 , 立即启动 ,tls证书 },  信令表::WEB服务器_新建_回复 => web_id )
    }
}




#[gen_特征_derive(MOD特征_web)]
impl 信令路由{
    async fn exec文本信令_web(&self,函数名:&str, mut 参数数组:Vec<String>)-> anyhow_Result<(bool,Value,Vec<String>)>{
        let 信令路由ref = self;
        let 结果 = match 函数名{
            "web" | "网络_WEB服务器_查询"=>{   json!(信令路由ref.WEB服务器_查询().await?)   }
            "网络_WEB服务器_新建"=>{
                if 参数数组.len() < 4 {  return Err(anyhow_err!("网络_WEB服务器_新建, 缺少参数:: <协议头>  <ip> <端口> <二维路由表>  <立即启动> <TLS证书路径数组>")) }  
                let tls证书 = if 参数数组.len() >= 6{  if let Ok(tls证书) =  serde_json::from_str::<Vec<String>>(&参数数组[5]){ Some(tls证书)   }else{ None }   }else{ None };
                let 立即启动 = if 参数数组.len() >= 5{ if 参数数组[4] =="true"{ Some(true) }else{ None }   }else{ None };
                let 路由表JSON = 参数数组.remove(3);
                let 端口 = 参数数组[2].parse::<u16>().ok();
                let ip = if 参数数组[1] =="null" { None }else{ Some(参数数组.remove(1)) };
                let 协议头 = if 参数数组[0]=="null" { None }else{ Some(参数数组.remove(0)) };
                
                let mut 路由表:HashMap<String,Vec<String>>  = HashMap::new();
                if let Ok(二维数组) =  serde_json::from_str::<Vec<Vec<String>>>(&路由表JSON){ 
                    for 单表 in &二维数组{
                        if 单表.len() >=2 {  路由表.insert(单表[0].clone(), 单表[1..].to_vec().clone());  }
                        else { eprintln!("网络_WEB服务器_新建, 路由表JSON 存在空数组")  }
                    }
                    json!(信令路由ref.WEB服务器_新建(协议头, ip, 端口, Some(路由表), 立即启动, tls证书).await?)  
                }else{
                    return Err(anyhow_err!("网络_WEB服务器_新建， 二维数组缺少参数:: [  [<base相对目录> <根目录>...],  [<base相对目录> <根目录>...]  ]"))
                }
            }
            "网络_WEB服务器_控制"=>{
                if 参数数组.len() < 2 {  return Err(anyhow_err!("网络_WEB服务器_销毁, 缺少参数::  <web_id> <控制>")) }  
                信令路由ref.WEB服务器_控制(参数数组[0].parse::<u64>()?, 参数数组.remove(1)  ).await?;
                json!(true)
            }
            _=>{ return Ok((false, json!(""), 参数数组)); }
        };
        Ok((true, 结果, Vec::new()))
    }
     
    fn WEB服务器_新建(&self,协议头:Option<String>, ip:Option<String>,端口: Option<u16>,路由表:Option<HashMap<String,Vec<String>>>, 立即启动:Option<bool>, tls证书:Option<Vec<String>>)-> impl 信令任务<原子ID>{
        core发布信令任务!(self, 信令表::WEB服务器_新建 { 协议头, ip ,端口 ,路由表 , 立即启动 ,tls证书 },  信令表::WEB服务器_新建_回复 => web_id )
    }
    
    fn WEB服务器_新建Builder(&self)->Builder_WEB服务器{  Builder_WEB服务器::new(self.clone())  }
    

    fn WEB服务器_查询(&self)-> impl 信令任务<Vec<WEB服务器信息>>{
        core发布信令任务!(self, 信令表::WEB服务器_查询{ web_id数组:Vec::new() },  信令表::WEB服务器_查询_回复 => 数组 )
    }
    fn WEB服务器_查询单个(&self, web_id:原子ID)-> impl 信令任务<WEB服务器信息> {
        core发布信令任务!(self, 信令表::WEB服务器_查询{ web_id数组: vec![web_id] },  信令表::WEB服务器_查询单个_回复 => 单个 )
    }
    fn WEB服务器_控制(&self, web_id:原子ID, 控制指令:impl AsRef<str>)-> impl 信令任务<原子ID>{
        core发布信令任务!(self, 信令表::WEB服务器_控制 { web_id , 控制指令:控制指令.as_ref().to_string() },  信令表::WEB服务器_控制_回复 => web_id )
    }
    fn emit_WEB服务器_已退出(&self, web_id: 原子ID, 原因:impl AsRef<str>) {  self.task发布信令_单向(信令表::WEB服务器_已退出 { web_id, 原因:原因.as_ref().to_string() });  }
    
}


#[derive(Clone, Serialize, Deserialize)]//可选特征
enum 信令表{
    WEB服务器_新建{       协议头:Option<String>, ip:Option<String> , 端口: Option<u16>,  路由表:Option<HashMap<String,Vec<String>>> , 立即启动:Option<bool>, tls证书:Option<Vec<String>>  },
    WEB服务器_新建_回复 {  web_id:原子ID          },
    WEB服务器_控制 {      web_id:原子ID, 控制指令:String      },
    WEB服务器_控制_回复{   web_id:原子ID          },
    WEB服务器_已退出{  web_id:原子ID    ,原因:String          },
    WEB服务器_查询{    web_id数组: Vec<原子ID>    },
    WEB服务器_查询_回复 { 数组: Vec<WEB服务器信息>  },
    WEB服务器_查询单个_回复 { 单个: WEB服务器信息   },

} 
impl信令特征!(信令表, 执行函数);


async fn 执行函数(信令路由:信令路由,id:信令ID,单个信令:信令表)->anyhow_Result<信令表>{
    let WEB服务器管理 = 全局_WEB服务器管理.get_or_init(||WEB服务器管理::new(信令路由.clone()));
    
    match 单个信令{
            信令表::WEB服务器_新建 { 协议头, ip ,端口 ,路由表, 立即启动 ,tls证书  } =>{
                let mut web_id = None;
                let 结果 =  WEB服务器管理.新建web服务器(协议头, ip,端口,路由表, tls证书)
                                .map(|返回|{
                                    web_id = Some(返回);
                                    信令表::WEB服务器_新建_回复 { web_id:返回 } 
                                })
                                .map_err(|err|{  anyhow_err!("信令表::WEB服务器_新建  {err}")   })?;
                if 立即启动.unwrap_or_default() && web_id.is_some(){
                    信令路由.WEB服务器_控制(web_id.unwrap(),"启动").await?;
                }
                anyhow_Ok信令!(结果)
            }
            信令表::WEB服务器_查询{ web_id数组 } =>{
                let mut 数组 = WEB服务器管理.查询web服务器(web_id数组.clone());
                if web_id数组.len() ==1{
                    let web_id = web_id数组[0];
                    if 数组.len() ==1{
                        anyhow_Ok信令!(信令表::WEB服务器_查询单个_回复 { 单个:数组.remove(0) })
                    }else{
                        anyhow_Err信令!("找不到此WEB服务器 web_id {web_id}")
                    }
                }else{
                    anyhow_Ok信令!(信令表::WEB服务器_查询_回复 { 数组 })
                }
            }
            信令表::WEB服务器_控制{ web_id,  控制指令  } =>{
                let 结果 = match 字符串转_WEB服务器控制指令(控制指令) {
                    Ok(指令)=> WEB服务器管理.控制web服务器(web_id, 指令).map(|_|  信令表::WEB服务器_控制_回复{ web_id } ),
                    Err(err)=> anyhow_Err信令!("{err}"),
                }?;
                anyhow_Ok信令!(结果)
            }
            信令表::WEB服务器_已退出{ web_id, 原因 }=>{
                return Err(anyhow_err!("WEB服务器_已退出 {web_id} -> {原因}"));
            }
            _ =>{ return Err(anyhow_err!("信令不存在")); }
    }
}


#[cfg(all(test,feature = "mod_web"))]
mod  测试{
    use super::*;
    #[cfg(all(test,feature = "mod_web"))]
    #[test]
    fn 测试1(){
        // 🔥🔥🔥 js child_process.spawn 调用二进制，必须带有  process.env  ，否则报错🔥🔥🔥
        let 信令路由 =  信令路由::default();   //  gio_磁盘查询数组   
        信令路由.clone().pool异步任务_block阻塞完成(async move{
            let out = 信令路由.网络_查询局域网内已打开端口的ip数组(vec![80]).await.unwrap();
            eprintln!("\n🌷结果🌷>>\n{:?}",json!(out) );
        }).ok();
    }


}









#[derive(Clone)]
pub struct  WEB服务器管理{
    信令路由:信令路由,
    记录WEB服务器数组: Arc<DashMap<原子ID,WEB服务器>>,
}


impl WEB服务器管理{
    pub fn new(信令路由:信令路由)->Self{
        Self { 
            信令路由,
            记录WEB服务器数组: Arc::new(DashMap::new()),
        }
    }
    pub fn 新建web服务器(&self, 协议头:Option<String>, ip:Option<String>,端口:Option<u16>,路由表:Option<HashMap<String,Vec<String>>>, tls证书: Option<Vec<String>> )->anyhow_Result<原子ID>{
        let web_id = 原子ID对象::next().0;
        let 信令路由_c1 = self.信令路由.clone();
        let 服务器 = WEB服务器::new(信令路由_c1, web_id, 协议头, ip ,端口 , 路由表,  tls证书)?;
        self.记录WEB服务器数组.insert(web_id, 服务器);
        Ok(web_id)
    }
    
    pub fn 查询web服务器(&self, web_id数组: Vec<原子ID>)->Vec<WEB服务器信息>{
        let mut 数组:Vec<WEB服务器信息> = Vec::new();
        for 服务器 in  self.记录WEB服务器数组.iter(){
            if web_id数组.len() > 0{
                if web_id数组.contains(服务器.key()){
                    let 信息 = 服务器.value().into();  // From特征
                    数组.push(信息);
                    if 数组.len()>= web_id数组.len(){ break; }     //已经找全
                }
            }else{
                let 信息 = 服务器.value().into();      // From特征
                数组.push(信息);
            }
        }
        数组
    }

    
    pub fn 控制web服务器(&self,web_id:原子ID, 控制指令:WEB服务器控制指令)->anyhow_Result<()>{ 
        let 服务器 = {  
            self.记录WEB服务器数组.get(&web_id)
                .map(|a| { a.clone() }) 
                .ok_or(anyhow_err!("WEB服务器_控制指令  {web_id} 错误, 找不到服务器 !!!"))?
        };
        match 控制指令{
            WEB服务器控制指令::启动=>{  服务器.启动服务器();  }
            WEB服务器控制指令::停止=>{  服务器.停止服务器();  }
            WEB服务器控制指令::反转启停=>{  
                let 状态 = { (*服务器.状态.lock()).clone() };
                match 状态 {
                    服务器状态::正常=>{  服务器.停止服务器(); }
                    服务器状态::已停止=>{ 服务器.启动服务器(); }
                }
            }
            WEB服务器控制指令::重启=>{  服务器.重启服务器();  }
            WEB服务器控制指令::销毁=>{  
                服务器.停止服务器();
                self.记录WEB服务器数组.remove(&web_id);
                print!("_开🌷_{}_🍊束_\n", json!(vec!["rust_WEB服务器_销毁".into(), web_id.to_string() ]) );
            }
            WEB服务器控制指令::销毁所有=>{
                for 服务器 in  self.记录WEB服务器数组.iter(){
                    服务器.停止服务器();
                    self.记录WEB服务器数组.remove(服务器.key());
                }
            }
        }
        Ok(())
    }
   
}







#[derive(Clone)]
pub struct WEB服务器{
    pub 信令路由:信令路由,
    pub web_id: 原子ID,
    pub 协议头:String,
    pub tls证书:Option<Vec<String>>, // 存储一对 路径
    pub ip:String,
    pub 端口:u16,
    pub 路由表:Arc<Option<HashMap<String,Vec<String>>>>,          // 相对路径    根目录 
    pub 共享数据: Arc<StateManager>,
    pub 时间戳:u128,
    pub 状态:Arc<Mutex<服务器状态>>,
    pub server_handle :Arc<Mutex<Option<ServerHandle>>>,
}






impl WEB服务器{
    pub fn new(信令路由:信令路由,  web_id: 原子ID, 协议头:Option<String>, ip:Option<String> ,端口:Option<u16>  ,路由表:Option<HashMap<String,Vec<String>>> , tls证书: Option<Vec<String>> )-> anyhow_Result<Self>{
        let 协议头 = if let Some(可用协议头) = 协议头{ 可用协议头 }else{ "http".to_string() };
        let 可用ip = if let Some(可用ip) = ip { 可用ip }else{ local_ip()?.to_string() };
        let 可用端口 = if let Some(可用端口)= 端口 { 可用端口  } else {  portpicker::pick_unused_port().ok_or(anyhow_err!("新建WEB服务器  找不到空闲端口"))?   };
        if portpicker::is_free(可用端口) == false { return Err(anyhow_err!("新建WEB服务器失败!!!  此端口被占用: {可用端口}"));  }
        
        let 服务器 = Self {
            信令路由,
            web_id, 
            协议头, tls证书,
            ip:可用ip,
            端口:可用端口,
            路由表:Arc::new(路由表),    // vite 中 base 相对本地文件是 ./      比如自定义  /lwleen-vitepress/
            共享数据:Arc::new(StateManager::new()), 
            时间戳:TIME时间::now_毫秒(),
            状态:Arc::new(Mutex::new(服务器状态::已停止)),       // 默认不启动服务器
            server_handle:Arc::new(Mutex::new(None)),
        };
        
        Ok(服务器)
    }
    

    pub fn run_loop服务器_阻塞线程(&mut self){
        信令路由::block_on_lite(Compat::new(loop_Li文件浏览器(self.clone())));
    }
    

    pub fn 停止服务器(&self){
        let 状态 = { (*self.状态.lock()).clone() };
        match 状态{
            服务器状态::已停止 => {  }
            服务器状态::正常=>{
                if let Some(handle) = &(*self.server_handle.lock()){ handle.stop_graceful(None); }
            }
        }
    }
    
    pub fn 启动服务器(&self){
        let mut 服务器_clone = self.clone();
        let 状态 = { (*self.状态.lock()).clone() };
        match 状态{
            服务器状态::正常=>{  }
            服务器状态::已停止 => {  
                std::thread::spawn(move || {   服务器_clone.run_loop服务器_阻塞线程();  });  
            }
        }
    }
    
    pub fn 重启服务器(&self){
        let mut 服务器_clone = self.clone();
        let 状态 = { (*self.状态.lock()).clone() };
        match 状态{
            服务器状态::正常=>{ 

            }
            服务器状态::已停止 => {  
                std::thread::spawn(move || {   服务器_clone.run_loop服务器_阻塞线程();  });  
            }
        }
    }
}




#[derive(Clone, EnumDisplay)]
pub enum 服务器状态 {
    正常,   
    已停止, 
}


pub fn 字符串转_WEB服务器控制指令(控制指令: impl AsRef<str>)->anyhow_Result<WEB服务器控制指令>{
    let 控制指令 = 控制指令.as_ref().to_string();
    let 指令 = match 控制指令.as_str(){
        "启动"   =>  WEB服务器控制指令::启动,
        "停止"   =>  WEB服务器控制指令::停止,
        "反转启停"=>  WEB服务器控制指令::反转启停,
        "重启"   =>  WEB服务器控制指令::重启,
        "销毁"   =>  WEB服务器控制指令::销毁, 
        "销毁所有"   =>  WEB服务器控制指令::销毁所有, 
        _=>{ return Err(anyhow_err!("🍅🍅🍅控制web服务器, 无法识别控制指令 <{控制指令}>"));   }
    };
    Ok(指令)
}



#[derive(Clone, Serialize, Deserialize, EnumDisplay)]
pub enum WEB服务器控制指令 {
    启动,
    停止, 
    反转启停,
    重启,  
    销毁, 
    销毁所有,
}
















//================ WEB服务器 ================

#[derive(Default,Serialize, Deserialize,Debug,Clone)]
pub struct WEB服务器信息{
    pub web_id: 原子ID,
    pub 基础url:String,
    pub 协议头:String,
    pub ip:String,
    pub 端口: u16,
    pub 路由表: std::collections::HashMap<String,Vec<String>>,
    pub 路由表路径数组:Vec<String>,
    pub 启动时间:u128,
    pub 时间戳:u128,
    pub 状态:String,
}


impl WEB服务器信息 {
    pub fn new(协议头:impl AsRef<str> ,ip:impl AsRef<str>, 端口:u16 ,路由表:Option<HashMap<String, Vec<String>>> )->Self{
        let 路径数组 = 路由表.as_ref().map(|表|{
                        let mut 数组 = Vec::new();
                        for (相对路径, 根路径) in 表{
                            数组.push(format!("{}://{}:{}{}",协议头.as_ref(),ip.as_ref(), 端口, 相对路径));
                        }
                        数组
                    }).unwrap_or_default();
        let 时间戳 = TIME时间::now_毫秒();
        Self{
            web_id:0,
            基础url:format!("{}://{}:{端口}",协议头.as_ref(),ip.as_ref()),
            协议头:协议头.as_ref().to_string(),
            ip:   ip.as_ref().to_string(),
            端口:  端口,
            路由表:路由表.unwrap_or_default(),
            路由表路径数组:路径数组,
            启动时间:时间戳,
            时间戳,
            状态:"".to_string(),
        }
    }
    pub fn 设置路由表(&mut self,路由表:HashMap<String, Vec<String>>){
        let mut 路径数组 = Vec::new();
        for (相对路径, 根路径) in &路由表{
            路径数组.push(format!("{}://{}:{}{}",&self.协议头,&self.ip, self.端口, 相对路径));
        }
        self.路由表 = 路由表;
        self.路由表路径数组 = 路径数组;
    }
}


impl From<&WEB服务器> for WEB服务器信息 {
    fn from(value: &WEB服务器) -> Self {
        let mut res = WEB服务器信息::new(value.协议头.clone(), value.ip.clone(), value.端口, (*value.路由表).clone());
        res.web_id = value.web_id;
        res.状态 = value.状态.lock().to_string();
        res.启动时间 = value.时间戳;
        res
    }
}





