use dioxus::prelude::*;

use crate::components::layout::icons;
use crate::util::model::member::Member;
use crate::util::model::session::Session;
use crate::util::model::user::User;
use std::collections::HashMap;

pub fn Auth() -> Element {
    let mut register = use_signal(|| false);

    rsx! {
        div {
            class: "flex flex-col items-center",
            h1 { class: "font-bold text-primary text-center text-2xl mt-16", "Waddinxveense Reddingsbrigade" },
            div {
                class: "card bg-base-200 mt-8 w-full max-w-lg shadow-xl",
                div {
                    class: "card-body",
                    div {
                        role: "tablist",
                        class: "tabs tabs-boxed bg-base-300 mx-auto w-full mb-6",
                        button {
                            onclick: move |_| register.set(false),
                            role: "tab",
                            class: "tab",
                            class: if !register() { "tab-active" },
                            "Inloggen"
                        },
                        button {
                            onclick: move |_| register.set(true),
                            role: "tab",
                            class: "tab",
                            class: if register() { "tab-active" },
                            "Registreren"
                        },
                    }
                    if !register() {
                        Login { }
                    } else {
                        Register { }
                    }
                }
            }
        }
    }
}

fn Login() -> Element {
    let mut input_email = use_signal(|| "".to_string());
    let mut input_password = use_signal(|| "".to_string());

    let submit = move |_| async move {
        if let Ok(_) = login(input_email(), input_password()).await {
            let window = web_sys::window().expect("Could not find window");
            window.location().reload().expect("Could not reload window");
        }
    };

    rsx! {
        label {
            class: "form-control w-full",
            div {
                class: "label",
                span { class: "label-text", "Email" },
            }
            input {
                r#type: "email",
                class: "input input-bordered w-full",
                value: "{input_email}",
                oninput: move |event| input_email.set(event.value())
            },
        }
        label {
            class: "form-control w-full mt-3",
            div {
                class: "label",
                span { class: "label-text", "Wachtwoord" },
            }
            input {
                r#type: "password",
                class: "input input-bordered w-full",
                value: "{input_password}",
                oninput: move |event| input_password.set(event.value())
            },
        }
        div {
            class: "card-actions mt-5",
            button {
                class: "btn btn-primary",
                onclick: submit,
                "Inloggen",
            }
        }
    }
}

fn Register() -> Element {
    let mut members: Signal<HashMap<String, Member>> = use_signal(|| HashMap::new());

    let mut input_registration_token = use_signal(|| "".to_string());
    let mut input_email = use_signal(|| "".to_string());
    let mut input_password = use_signal(|| "".to_string());
    let mut input_password_repeat = use_signal(|| "".to_string());

    let submit = move |_| async move {
        let members_set: Vec<String> = members().into_keys().collect();

        if let Ok(_) = register(input_email(), input_password(), members_set).await {
            let window = web_sys::window().expect("Could not find window");
            window.location().reload().expect("Could not reload window");
        }
    };

    rsx! {
        label {
            class: "form-control w-full join-item",
            div {
                class: "label",
                span { class: "label-text", "Registratie code" },
            }
            div {
                class: "w-full join",
                input {
                    r#type: "text",
                    class: "input input-bordered w-full join-item",
                    value: "{input_registration_token}",
                    oninput: move |event| input_registration_token.set(event.value())
                },
                button {
                    class: "btn join-item btn-neutral",
                    onclick: move |_| async move {
                        if let Ok(res) = fetch_member(input_registration_token()).await {
                            members.write().insert(res.id.clone(), res);
                            input_registration_token.set("".to_string());
                        }
                    },
                    icons::UserPlus {},
                    "Toevoegen",
                }
            }
            div {
                class: "flex gap-1 pt-2 flex-wrap",
                for (id, member) in members() {
                    div {
                        class: "badge badge-md badge-neutral h-8 gap-1 hover:cursor-pointer hover:line-through whitespace-nowrap",
                        onclick: move |_| {
                            members.write().remove(&id);
                        },
                        "{member.name.full}"
                        icons::XMark {},
                    }
                }
            }
            label {
                class: "form-control w-full mt-3",
                div {
                    class: "label",
                    span { class: "label-text", "Email" },
                }
                input {
                    r#type: "email",
                    class: "input input-bordered w-full",
                    value: "{input_email}",
                    oninput: move |event| input_email.set(event.value())
                },
            }
            label {
                class: "form-control w-full mt-3",
                div {
                    class: "label",
                    span { class: "label-text", "Wachtwoord" },
                }
                input {
                    r#type: "password",
                    class: "input input-bordered w-full",
                    value: "{input_password}",
                    oninput: move |event| input_password.set(event.value())
                },
            }
            label {
                class: "form-control w-full mt-3",
                div {
                    class: "label",
                    span { class: "label-text", "Herhaal wachtwoord" },
                }
                input {
                    r#type: "password",
                    class: "input input-bordered w-full",
                    value: "{input_password_repeat}",
                    oninput: move |event| input_password_repeat.set(event.value())
                },
            }
        }
        div {
            class: "card-actions mt-5",
            button {
                class: "btn btn-primary",
                onclick: submit,
                "Registreren"
            }
        }
    }
}

#[server]
async fn login(email: String, password: String) -> Result<(), ServerFnError> {
    // Verify username and password
    let user_id = User::verify_credentials(email, password).await?;

    // Create a new session
    let session = Session::new(user_id).await?;
    session.set_cookie()?;

    Ok(())
}

#[server]
async fn register(
    email: String,
    password: String,
    member_ids: Vec<String>,
) -> Result<(), ServerFnError> {
    // Creat a new user
    let user = User::new(email, password, member_ids).await?;

    // Generate a session and set the cookie
    let session = Session::new(user.id).await?;
    session.set_cookie()?;

    Ok(())
}

#[server]
async fn fetch_member(registration_token: String) -> Result<Member, ServerFnError> {
    let member = Member::fetch_from_registration_token(registration_token).await?;

    match member {
        Some(m) => Ok(m),
        None => Err(ServerFnError::new("Lid niet gevonden")),
    }
}
