use std::{collections::HashMap, path::PathBuf};

use http::handling::{
    file_handlers::NamedFile,
    methods::Method,
    request::{Request, ParseFormError},
    response::{Outcome, Response, Status},
    routes::{Data, Route},
};

fn hashmap_to_string(map: &HashMap<&str, Result<&str, ParseFormError>>) -> String {
    let mut result = String::new();
    for (key, value) in map {
        result.push_str(key);
        result.push('=');
        result.push_str(value.as_ref().unwrap());
        result.push(';');
    }
    result.pop(); // Remove the trailing semicolon if desired
    result
}

fn handle_static_hi(request: Request<>, data: Data) -> Outcome<Response, Status, Data> {
    let keys = if let Ok(keys) = request.get_get_form_keys(&["asdf", "jkl"]) {
        keys
    } else {
        return Outcome::Forward(data);
    };
    let response = hashmap_to_string(&keys);
    Outcome::Success(Response {
        headers: vec![],
        cookies: None,
        status: Some(Status::Ok),
        body: Box::new(response),
    })
    // Outcome::Forward(data)
}

fn handler(request: Request<>, _data: Data) -> Outcome<Response, Status, Data> {
    let response = fileserver(request.uri.raw_string().unwrap().strip_prefix("static/").unwrap());
    let response = match response {
        Ok(dat) => Response {
            headers: vec![],
            cookies: None,
            status: Some(Status::Ok),
            body: Box::new(dat),
        },
        Err(_) => return Outcome::Failure(Status::NotFound),
    };
    Outcome::Success(response)
}

fn fileserver(path: &str) -> Result<NamedFile, Status> {
    NamedFile::open(PathBuf::from("static/".to_string() + path))
}

fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Data> {
    if data.is_empty() {
        return Outcome::Forward(data);
    }
    let dat = if let Ok(val) = request.get_post_data(&["message"], &data) {
        post_hi(String::from_utf8_lossy(val.get("message").unwrap().as_ref().unwrap()).to_string())
    } else {
        return Outcome::Failure(Status::BadRequest);
    };
    Outcome::Success(Response {
        headers: vec![],
        cookies: None,
        status: Some(Status::Ok),
        body: Box::new(dat),
    })
}

fn post_hi(msg: String) -> String {
    msg
}

#[tokio::main]
async fn main() {
    let fileserver = Route {
        format: None,
        handler,
        name: Some("file_server"),
        uri: "static/<path..>",
        method: Method::Get,
        rank: 1,
    };

    let post_test = Route {
        format: None,
        handler: post_hi_handler,
        name: Some("post_test"),
        uri: "post",
        method: Method::Post,
        rank: 0,
    };

    let static_hi = Route {
        format: None,
        handler: handle_static_hi,
        name: Some("Handle_Static_hi"),
        uri: "static/hi",
        method: Method::Get,
        rank: 0,
    };
    http::build("127.0.0.1:8080", "127.0.0.1:8443")
        .await
        .mount("/", vec![fileserver, post_test, static_hi])
        .mount("/post/", vec![post_test])
        .launch()
        .await;
}