use crate::request::{Request};
use crate::websocket::{CloseCode, ErrorCode, Message, MessageMode, MessageType};
use openssl::ssl::SslStream;
use std::io::{BufRead, BufReader, ErrorKind, Read, Write};
use std::net::TcpStream;
use std::{thread};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use hpack::{Decoder};
use log::{info, warn};
use crate::{HttpError, Method, Uri};

#[derive(Debug, Clone)]
pub enum Scheme {
    Http(Arc<Mutex<BufReader<TcpStream>>>),
    Https(Arc<Mutex<BufReader<SslStream<TcpStream>>>>),
}

impl Scheme {
    /// 读取一行
    pub fn read_line(&mut self) -> Result<String, HttpError> {
        let mut line = String::new();
        loop {
            let result = match self {
                Scheme::Http(stream) => {
                    let mut reader = stream.lock().unwrap();
                    reader.read_line(&mut line)
                }
                Scheme::Https(stream) => {
                    let mut reader = stream.lock().unwrap();
                    reader.read_line(&mut line)
                }
            };
            return match result {
                Ok(0) => Err(HttpError::new(500, "read_line: 客户端主动关闭")),
                Ok(_) => Ok(line),
                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                    // ⚠️ 当前无数据可读，稍后再试
                    thread::sleep(Duration::from_millis(100));
                    continue;
                }
                Err(e) => Err(HttpError::new(500, format!("read_line: {}", e.to_string().as_str()).as_str())),
            };
        }
    }

    /// 读取
    pub fn read(&mut self) -> Result<Vec<u8>, HttpError> {
        let mut buf = [0u8; 1024 * 1024];
        loop {
            let result = match self {
                Scheme::Http(stream) => {
                    let mut stream = stream.lock().unwrap();
                    stream.read(&mut buf)
                }
                Scheme::Https(stream) => {
                    let mut stream = stream.lock().unwrap();
                    stream.read(&mut buf)
                }
            };
            return match result {
                Ok(0) => Err(HttpError::new(500, "read: 客户端主动关闭")),
                Ok(n) => Ok(buf[..n].to_vec()),
                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                    // ⚠️ 当前无数据可读，稍后再试
                    thread::sleep(Duration::from_millis(100));
                    continue;
                }
                Err(e) => Err(HttpError::new(500, format!("read: {}", e.to_string().as_str()).as_str())),
            };
        }
    }
    /// 指定长度
    fn read_data(&self, init_data: &mut Vec<u8>, length: usize) -> Result<(), HttpError> {
        loop {
            if init_data.len() >= length {
                return Ok(());
            }
            let mut buf = [0u8; 1024 * 1024];
            let result = match self {
                Scheme::Http(stream) => stream.lock().unwrap().get_mut().read(&mut buf),
                Scheme::Https(stream) => stream.lock().unwrap().read(&mut buf)
            };
            return match result {
                Ok(0) => Err(HttpError::new(500, "read_data: 客户端主动关闭")),
                Ok(n) => {
                    init_data.extend(&buf[..n]);
                    Ok(())
                }
                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                    // ⚠️ 当前无数据可读，稍后再试
                    thread::sleep(Duration::from_millis(100));
                    continue;
                }
                Err(e) => Err(HttpError::new(500, format!("read: {}", e.to_string().as_str()).as_str())),
            };
        }
    }

    /// 写入
    pub fn write(&mut self, data: &[u8]) -> Result<(), HttpError> {
        let mut off = 0;
        loop {
            let result = match self {
                Scheme::Http(stream) => stream.lock().unwrap().get_ref().write(&data[off..]),
                Scheme::Https(stream) => stream.lock().unwrap().get_mut().write(&data[off..])
            };
            match result {
                Ok(0) => return Err(HttpError::new(500, "write: 客户端主动关闭")),
                Ok(e) => {
                    if e != data.len() {
                        off = e;
                        continue;
                    }
                    let _ = match self {
                        Scheme::Http(stream) => stream.lock().unwrap().get_mut().flush(),
                        Scheme::Https(stream) => stream.lock().unwrap().get_mut().flush()
                    };
                    return Ok(());
                }
                Err(ref e) if e.kind() == ErrorKind::WouldBlock || e.kind() == ErrorKind::Interrupted => {
                    // 等待可写（理想用 epoll/kqueue/IOCP；这里先简单 sleep）
                    thread::sleep(Duration::from_millis(2));
                    continue;
                }
                Err(e) => return Err(HttpError::new(500, format!("write: {}", e.to_string().as_str()).as_str())),
            };
        }
    }

    pub fn read_ws_data(&mut self) -> Result<Message, HttpError> {
        let mut response = vec![];
        loop {
            let mut buffer = [0u8; 1024 * 1024];
            let res = match self {
                Scheme::Http(stream) => {
                    stream.lock().unwrap().read(&mut buffer)
                }
                Scheme::Https(ref mut stream) => {
                    stream.lock().unwrap().read(&mut buffer)
                }
            };
            return match res {
                Ok(0) => Ok(Message {
                    mode: MessageMode::Client,
                    message_type: MessageType::Close,
                    payload: vec![],
                    text: CloseCode::ClientClose.str(),
                    close: CloseCode::ClientClose,
                    error: ErrorCode::None,
                }),
                Ok(n) => {
                    response.extend(buffer[..n].to_vec());
                    let message = Message::parse_message(&mut response);
                    if let MessageType::Continuation = message.message_type { continue; }
                    Ok(message)
                }
                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                    continue;
                }
                Err(e) => Ok(Message {
                    mode: MessageMode::Client,
                    message_type: MessageType::Error,
                    payload: vec![],
                    text: e.to_string(),
                    close: CloseCode::Other,
                    error: ErrorCode::Unknown,
                })
            };
        }
    }

    pub fn client_ip(&mut self) -> String {
        match self {
            Scheme::Http(stream) => {
                match stream.lock().unwrap().get_mut().peer_addr() {
                    Ok(e) => e.ip().to_string(),
                    Err(_) => "未知".to_string(),
                }
            }
            Scheme::Https(stream) => {
                stream.lock().unwrap().get_mut().get_ref().peer_addr().unwrap().ip().to_string()
            }
        }
    }
    pub fn server_ip(&mut self) -> String {
        match self {
            Scheme::Http(stream) => {
                stream.lock().unwrap().get_mut().local_addr().unwrap().ip().to_string()
            }
            Scheme::Https(stream) => {
                stream.lock().unwrap().get_mut().get_ref().local_addr().unwrap().ip().to_string()
            }
        }
    }
    /// 读取HTTP2
    pub fn http2_packet(&mut self, init_data: &mut Vec<u8>) -> Result<(Vec<u8>, FrameType, u8, u32), HttpError> {
        let bytes = init_data;
        self.read_data(bytes, 9)?;
        let headers = bytes.drain(..9).collect::<Vec<u8>>();
        let length = ((headers[0] as u32) << 16) | (u32::from(headers[1]) << 8) | u32::from(headers[2]);
        let frame_type = headers[3];
        let flags = headers[4];
        let stream_id = u32::from_be_bytes([headers[5], headers[6], headers[7], headers[8]]) & 0x7FFF_FFFF;
        self.read_data(bytes, length as usize)?;
        let payload = bytes.drain(..length as usize).collect::<Vec<u8>>();
        Ok((payload, FrameType::from(frame_type), flags, stream_id))
    }
    /// 读取HTTP2消息头
    pub fn http2_handle_header(&mut self, data: &mut Vec<u8>, request: &mut Request) -> Result<(), HttpError> {
        loop {
            let (payload, frame_type, _, stream_id) = self.http2_packet(data)?;
            if request.config.debug {
                info!("frame_type: {frame_type:?} stream_id: {stream_id} payload: {}", payload.len());
            }
            match frame_type {
                FrameType::Settings => {
                    if !payload.is_empty() {
                        self.http2_init_settings()?;
                    } else {
                        self.http2_settings()?;
                    }
                }
                FrameType::WindowUpdate => {
                    if payload.len() == 4 {
                        let raw = u32::from_be_bytes(payload.clone().try_into().unwrap());
                        let increment = raw & 0x7FFF_FFFF; // 屏蔽最高位保留位
                        info!("WindowUpdate: increment = {} {:?}", increment,payload);
                    } else {
                        return Err(HttpError::new(400, format!("Invalid WindowUpdate frame length: {}", payload.len()).as_str()));
                    }
                }
                FrameType::Headers => {
                    let mut decoder = Decoder::new();
                    let headers = decoder.decode(&payload).unwrap();
                    if request.config.debug {
                        println!("=================请求头 {:?}=================", thread::current().id());
                    }
                    for (name, value) in headers {
                        let header_name = String::from_utf8_lossy(name.as_slice());
                        let header_value = String::from_utf8_lossy(value.as_slice());
                        if request.config.debug {
                            println!("{header_name}: {header_value}");
                        }
                        match header_name.as_ref() {
                            ":method" => request.method = Method::from(header_value.as_ref()),
                            ":path" => request.uri = Uri::from(header_value.as_ref()),
                            ":scheme" => request.set_header("scheme", header_value.as_ref())?,
                            ":authority" => request.set_header("host", header_value.as_ref())?,
                            _ => request.set_header(&header_name, &header_value)?
                        }
                    }
                    if request.config.debug {
                        println!("====================================================");
                    }
                    return Ok(());
                }
                _ => return Err(HttpError::new(400, format!("Invalid {frame_type:?}").as_str()))
            }
        }
    }
    /// 读取HTTP2消息体
    pub fn http2_handle_body(&mut self, data: &mut Vec<u8>, request: Request) -> Result<Vec<u8>, HttpError> {
        let mut body = vec![];
        loop {
            let (payload, frame_type, flags, stream_id) = self.http2_packet(data)?;
            if request.config.debug {
                info!("frame_type: {frame_type:?} flags: {flags} stream_id: {stream_id} data: {}",payload.len());
            }
            match frame_type {
                FrameType::Data => {
                    if flags == 1 {
                        body.extend(payload);
                        return Ok(body);
                    }
                    body.extend(payload);
                }
                FrameType::Headers => {}
                FrameType::RstStream => {}
                FrameType::Settings => {
                    if !payload.is_empty() {
                        self.http2_init_settings()?;
                    } else {
                        self.http2_settings()?;
                    }
                }
                FrameType::Ping => {}
                FrameType::Goaway => {
                    let text = unsafe { String::from_utf8_unchecked(payload) };
                    //if text.as_str() == "SETTINGS expected" {}
                    if request.config.debug {
                        warn!("Goaway: {text}");
                    }
                    return Ok(vec![]);
                }
                FrameType::WindowUpdate => {
                    if request.config.debug {
                        let text = unsafe { String::from_utf8_unchecked(payload) };
                        info!("WindowUpdate: {text}");
                    }
                }
                FrameType::Continuation => {}
                FrameType::None => {}
            }
        }
    }
    /// 发送HTTP2认证参数
    pub fn http2_init_settings(&mut self) -> Result<(), HttpError> {
        let settings_frame = vec![
            0x00, 0x00, 0x00, // length = 0
            0x04,             // type = SETTINGS
            0x00,             // flags = none
            0x00, 0x00, 0x00, 0x00, // stream id = 0
            0x00, 0x01,       // identifier: SETTINGS_HEADER_TABLE_SIZE
            0x40, 0x00        // value: 16384
        ];
        self.write(settings_frame.as_slice())?;
        Ok(())
    }
    pub fn http2_settings(&mut self) -> Result<(), HttpError> {
        let settings_frame = vec![
            0x00, 0x00, 0x00, // length = 0
            0x04,             // type = SETTINGS
            0x01,             // flags = none
            0x00, 0x00, 0x00, 0x00, // stream id = 0
        ];
        self.write(settings_frame.as_slice())?;
        Ok(())
    }
    pub fn http2_goaway(&mut self, last_stream_id: u32, error_code: u32) -> Result<(), HttpError> {
        // 构造帧头
        let mut frame = Vec::new();
        frame.extend_from_slice(&[0x00, 0x00, 0x08]); // length
        frame.push(0x07); // type = GOAWAY
        frame.push(0x00); // flags = none
        frame.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); // stream id = 0
        frame.extend_from_slice(&last_stream_id.to_be_bytes());
        frame.extend_from_slice(&error_code.to_be_bytes());
        self.write(frame.as_slice())?;
        Ok(())
    }
    fn get_http2_data(&self, bytes: &mut Vec<u8>, length: usize, request: &mut Request) -> Result<(), HttpError> {
        loop {
            if bytes.len() >= length {
                return Ok(());
            }
            let mut buf = [0u8; 1024 * 1024];
            let usize = match self {
                Scheme::Http(stream) => {
                    match stream.lock().unwrap().get_mut().read(&mut buf) {
                        Ok(e) => e,
                        Err(e) => return Err(HttpError::new(500, format!("读取客户端http消息体失败: {e}").as_str()))
                    }
                }
                Scheme::Https(stream) => match stream.lock().unwrap().read(&mut buf) {
                    Ok(e) => e,
                    Err(e) => return Err(HttpError::new(500, format!("读取客户端https消息体失败: {e}").as_str()))
                },
            };
            request.body_data.extend(&buf[..usize]);
            bytes.extend(&buf[..usize]);
            if bytes.len() >= length {
                return Ok(());
            }
        }
    }
    pub fn get_http2_packet(&self, bytes: &mut Vec<u8>, request: &mut Request) -> Result<(Vec<u8>, FrameType, u8, u32), HttpError> {
        self.get_http2_data(bytes, 9, request)?;
        let headers = bytes.drain(..9).collect::<Vec<u8>>();
        let length = ((headers[0] as u32) << 16) | (u32::from(headers[1]) << 8) | u32::from(headers[2]);
        let frame_type = headers[3];
        let flags = headers[4];
        let stream_id = u32::from_be_bytes([headers[5], headers[6], headers[7], headers[8]]) & 0x7FFF_FFFF;
        self.get_http2_data(bytes, length as usize, request)?;
        let payload = bytes.drain(..length as usize).collect::<Vec<u8>>();
        Ok((payload, FrameType::from(frame_type), flags, stream_id))
    }
}
#[derive(Debug)]
pub enum FrameType {
    Data,
    Headers,
    RstStream,
    Settings,
    Ping,
    Goaway,
    WindowUpdate,
    Continuation,
    None,
}
impl FrameType {
    fn from(code: u8) -> FrameType {
        match code {
            0x00 => FrameType::Data,
            0x01 => FrameType::Headers,
            0x03 => FrameType::RstStream,
            0x04 => FrameType::Settings,
            0x06 => FrameType::Ping,
            0x07 => FrameType::Goaway,
            0x08 => FrameType::WindowUpdate,
            0x09 => FrameType::Continuation,
            _ => FrameType::None,
        }
    }
}

/// HTTP协议版本
#[derive(Clone, Debug)]
pub enum Protocol {
    HTTP1_0,
    HTTP1_1,
    HTTP2,
    HTTP3,
    Other(String),
}

impl Protocol {
    pub fn from(name: &str) -> Self {
        match name.to_lowercase().as_str() {
            "http/1.0" => Protocol::HTTP1_0,
            "http/1.1" => Protocol::HTTP1_1,
            "http/2.0" | "http/2" => Protocol::HTTP2,
            "http/3.0" | "http/3" => Protocol::HTTP3,
            _ => Protocol::Other(name.to_lowercase())
        }
    }
    pub fn str(&self) -> &str {
        match self {
            Protocol::HTTP1_0 => "HTTP/1.0",
            Protocol::HTTP1_1 => "HTTP/1.1",
            Protocol::HTTP2 => "HTTP/2.0",
            Protocol::HTTP3 => "HTTP/3.0",
            Protocol::Other(protocol) => protocol.as_str(),
        }
    }
}