// use std::net::SocketAddr;

use std::{collections::HashMap, error::Error, fmt::Display};

use crate::utils::mime::mime_enum::Mime;

use super::{
    methods::Method,
    routes::{Data, Uri},
};

type HeaderMap = Vec<String>;
#[derive(Clone)]
pub struct Request<'a> {
    pub uri: Uri<'a>,
    pub headers: HeaderMap,
    pub method: Method,
    // pub connection: ConnectionMeta,
}

// struct ConnectionMeta {
//     remote: Option<SocketAddr>,
//     // certificates
// }

#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum MediaType {
    Json,
    Plain,
    Html,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum ParseErrors {
    NoData,
    BadData,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ParseFormError {
    pub error: ParseErrors,
}

impl Display for ParseFormError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.error)
    }
}

impl Display for ParseErrors {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ParseErrors::NoData => write!(f, "No Data at key"),
            ParseErrors::BadData => write!(f, "Bad Data at key"),
        }
    }
}

impl Error for ParseFormError {}

impl Request<'_> {
    pub fn can_have_body(&self) -> bool {
        match self.method {
            Method::Post | Method::Put | Method::Patch | Method::Delete => true,
            _ => false,
        }
    }
    pub fn mandatory_body(&self) -> bool {
        match self.method {
            Method::Post | Method::Put | Method::Patch => true,
            _ => false,
        }
    }
    pub fn get_get_form_keys<'a>(
        &'a self,
        keys: &'a [&str],
    ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
        let data = if let Some(val) = self.uri.split_once("?") {
            val
        } else {
            return Err(ParseFormError {
                error: ParseErrors::NoData,
            });
        };
        let data = data
            .1
            .split("&")
            .map(|kvp| kvp.split_once("="))
            .collect::<Vec<Option<(&str, &str)>>>();

        let mut values: HashMap<&str, &str> = HashMap::new();
        for kvp in data {
            let kvp = if let Some(kvp) = kvp {
                kvp
            } else {
                continue;
            };
            values.insert(kvp.0, kvp.1);
        }
        let mut response = HashMap::new();
        for key in keys {
            let entry = if let Some(val) = values.get(key) {
                Ok(*val)
            } else {
                Err(ParseFormError {
                    error: ParseErrors::NoData,
                })
            };
            response.insert((*key).into(), entry);
        }
        Ok(response)
    }

    pub fn get_post_data<'a>(
        &'a self,
        keys: &[&'a str],
        data: &Data,
    ) -> Result<HashMap<&str, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
        let post_type = if let Some(val) = self
            .headers
            .iter()
            .find(|header| header.contains("Content-Type: "))
        {
            if let Ok(mime_type) = val.strip_prefix("Content-Type: ").unwrap().trim().parse() {
                mime_type
            } else {
                return Err(ParseFormError {
                    error: ParseErrors::NoData,
                });
            }
        } else {
            return Err(ParseFormError {
                error: ParseErrors::NoData,
            });
        };

        let data = data.buffer.as_slice();
        let mut keymap: HashMap<&str, Result<Vec<u8>, ParseFormError>> =
            HashMap::with_capacity(keys.len());
        for key in keys {
            keymap.entry(key).or_insert(Err(ParseFormError {
                error: ParseErrors::NoData,
            }));
        }
        match post_type {
            Mime::ApplicationXWwwFormUrlencoded => {
                for kvp in data.split(|byte| *byte == b'&') {
                    let kvp = kvp.split(|byte| *byte == b'=').collect::<Vec<&[u8]>>();
                    let key = if let Some(kv) = kvp.get(0) {
                        kv
                    } else {
                        return Err(ParseFormError {
                            error: ParseErrors::BadData,
                        });
                    };
                    let key = if let Ok(kv) = String::from_utf8(key.to_vec()) {
                        kv
                    } else {
                        return Err(ParseFormError {
                            error: ParseErrors::BadData,
                        });
                    };
                    let value = kvp.get(1).ok_or(ParseFormError {
                        error: ParseErrors::NoData,
                    });
                    let thing = if let Some(val) = keymap.get_mut(key.as_str()) {
                        val
                    } else {
                        continue;
                    };
                    *thing = match value {
                        Ok(val) => Ok(val.to_vec()),
                        Err(err) => Err(err),
                    }
                }
            }
            _ => {
                return Err(ParseFormError {
                    error: ParseErrors::BadData,
                })
            }
        };
        Ok(keymap)
    }

    // pub fn get_post_text_form_key(
    //     &self,
    //     keys: &[&str],
    //     data: &Data,
    // ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
    //     let mut post_type = self
    //         .headers
    //         .iter()
    //         .find(|header| header.contains("Content-Type: "))
    //         .unwrap()
    //         .to_string();
    //
    //     post_type = post_type
    //         .strip_prefix("Content-Type: ")
    //         .unwrap()
    //         .to_string();
    //
    //     let post_type: Vec<&str> = post_type.trim().split(';').collect();
    //     let mime_type = post_type[0].parse().unwrap();
    //
    //     // let data = String::from_utf8(vec)
    //
    //     let mut result = HashMap::new();
    //     match mime_type {
    //         Mime::ApplicationXWwwFormUrlencoded => {
    //             let data = String::from_utf8(data.buffer.clone()).unwrap();
    //             let kvps = data
    //                 .split("&")
    //                 .map(|kvp| kvp.split_once("=").unwrap())
    //                 .collect::<HashMap<&str, &str>>();
    //
    //             for key in keys {
    //                 let entry = if let Some(val) = kvps.get(key) {
    //                     Ok(*val)
    //                 } else {
    //                     Err(ParseFormError {
    //                         error: ParseErrors::NoData,
    //                     })
    //                 };
    //                 result.insert(*key, entry);
    //             }
    //             Ok(result)
    //         }
    //         Mime::MultipartFormData => {
    //             let from_req = post_type[1..]
    //                 .iter()
    //                 .find(|val| val.contains("boundary="))
    //                 .unwrap()
    //                 .strip_prefix("boundary=")
    //                 .unwrap();
    //             let mut boundary = b"--".to_vec();
    //             boundary.extend_from_slice(from_req.trim_matches('"').as_bytes());
    //             let mut end_boundary = boundary.clone();
    //             end_boundary.extend_from_slice(b"--");
    //             boundary.extend_from_slice(&[b'\r']);
    //             let parts = data
    //                 .buffer
    //                 .split(|byte| byte == &b'\n')
    //                 .collect::<Vec<&[u8]>>();
    //
    //             let mut boundary_found = false;
    //             let mut current_key: Option<&str> = None;
    //             let mut result: HashMap<&str, Vec<u8>> = HashMap::new();
    //             for part in parts {
    //                 if part == [] {
    //                     continue;
    //                 }
    //                 if part == end_boundary {
    //                     break;
    //                 }
    //                 if !boundary_found && part == boundary {
    //                     current_key = None;
    //                     boundary_found = true;
    //                     continue;
    //                 }
    //                 if part.starts_with(b"Content-Disposition: form-data; name=") {
    //                     let headers = part
    //                         .split(|byte| byte == &b';')
    //                         .filter(|header| !header.is_empty())
    //                         .collect::<Vec<_>>();
    //                     if headers.len() < 2 {
    //                         continue;
    //                     }
    //                     let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
    //                     if name.len() != 2 {
    //                         continue;
    //                     }
    //                     let mkey = String::from_utf8_lossy(name[1])
    //                         .as_ref()
    //                         .trim_end()
    //                         .trim_matches('"')
    //                         .to_owned();
    //                     for i in keys {
    //                         if *i == mkey {
    //                             current_key = Some(&mkey);
    //                         }
    //                     }
    //                     boundary_found = false;
    //                 } else if let Some(key) = current_key {
    //                     if None == result.get(key) {
    //                         result.insert(key, part.to_vec());
    //                         continue;
    //                     }
    //                     result.get_mut(key).unwrap().extend_from_slice(part);
    //                 }
    //             }
    //             if result.len() == 0 {
    //                 return Err(ParseFormError {
    //                     error: ParseErrors::NoData,
    //                 });
    //             }
    //             let return_result: HashMap<&str, Result<&str, ParseErrors>> =
    //                 HashMap::with_capacity(keys.len());
    //
    //             for key in keys {
    //                 let val = result.get(key).ok_or(ParseFormError {
    //                     error: ParseErrors::NoData,
    //                 }).map(|value| String::from_utf8(value))
    //                 let val = if let Ok(str) = String::from_utf8(val) {
    //                     Ok(str)
    //                 } else {
    //                     Err(ParseFormError {
    //                         error: ParseErrors::BadData,
    //                     })
    //                 };
    //             }
    //         }
    //         _ => Err(ParseFormError {
    //             error: ParseErrors::BadData,
    //         }),
    //     }
    // }
}

#[cfg(test)]
mod test {
    use crate::handling::routes::Data;

    use super::Request;

    #[test]
    fn try_post_text() {
        let req = Request {
            uri: "",
            headers: vec!["Content-Type: application/x-www-form-urlencoded".to_string()],
            method: crate::handling::methods::Method::Post,
        };
        let data = Data {
            buffer: b"message=23&message1=24".to_vec(),
            is_complete: true,
        };
        assert_eq!(
            vec![&Ok(b"23".to_vec()), &Ok(b"24".to_vec())],
            req.get_post_data(&["message", "message1"], &data)
                .unwrap()
                .values()
                .collect::<Vec<_>>()
        );
    }
}