use yew::prelude::*;
use web_sys::{Event, HtmlInputElement, HtmlSelectElement, HtmlDialogElement};
use web_sys::wasm_bindgen::JsCast;
use gloo_net::http::Request;
use serde::{Serialize, Deserialize};
use yew_icons::{Icon, IconData};

const API_BASE: &str ="http://172.16.0.155:3000/api/fs";
#[derive(Serialize, Deserialize)]
pub struct Did {
    id: i32,
    did_number: String,
    target_type: String,
    target: Option<String>,
    active: bool,
    trunk: String,
}

#[derive(Properties, PartialEq)]
pub struct DidProps {
    pub did_id: i32,
    pub did_number: String,
    pub target_type: String,
    pub target: String,
    pub active: bool,
    pub trunk: String,
    pub on_changed: Callback<()>
}

#[component]
pub fn DidComponent(props: &DidProps) -> Html {
    let id = props.did_id;
    let changed = use_state(||false);
    let did_number = use_state(||props.did_number.clone());
    let target_type = use_state(||props.target_type.clone());
    let target = use_state(||props.target.clone());
    let active= use_state(||props.active);
    let trunk= use_state(||props.trunk.clone());
    let on_changed = props.on_changed.clone();
    let dialog_ref: NodeRef = use_node_ref(); 

    let handle_did_input = {
        let did_number = did_number.clone();
        let changed = changed.clone();
        Callback::from(move |event: InputEvent| {            
            let did_number = did_number.clone();
            let t = event.target().and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
            if let Some(input) = t {
                did_number.set(input.value());
            }
            changed.set(true);
        }
    )};

    let handle_target_input = {
        let  target = target.clone();
        let changed = changed.clone();
        Callback::from(move |event: InputEvent| {            
            let target = target.clone();
            let t = event.target().and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
            if let Some(input) = t {
                target.set(input.value());
            }
            changed.set(true);
        }
    )};

    let handle_active_change = {
        let  active = active.clone();
        let changed = changed.clone();
        Callback::from(move |event: Event| {            
            let active = active.clone();
            let t = event
                .target()
                .and_then(|t| t.dyn_into::<HtmlInputElement>().ok());
            if let Some(input) = t {
                active.set(input.checked());
            }
            changed.set(true);
        }
    )};

    let handle_target_type_change = {
        let target_type = target_type.clone();
        let changed = changed.clone();
        Callback::from(move |event: Event| {
            let t = event
                .target()
                .and_then(|t| t.dyn_into::<HtmlSelectElement>().ok())
                .unwrap();
            target_type.set(t.value());
            changed.set(true);
        }
    )};

    let handle_trunk_change = {
        let trunk = trunk.clone();
        let changed = changed.clone();
        Callback::from(move |event: Event| {
            let t = event
                .target()
                .and_then(|t| t.dyn_into::<HtmlSelectElement>().ok())
                .unwrap();
            trunk.set(t.value());
            changed.set(true);
        }
    )};    
    let handle_save = {
        let changed = changed.clone();
        let did_number = did_number.clone();
        let target_type = target_type.clone();
        let target = target.clone();
        let active = active.clone();
        let on_changed = on_changed.clone();
        Callback::from(move |_| {
            let changed = changed.clone();
            let on_changed = on_changed.clone();
            let did = Did {
                id,
                did_number: (*did_number).clone(),
                target_type: (*target_type).clone(),
                target: Some((*target).clone()),
                active: (*active).clone(),
                trunk: (*trunk).clone(),
            };
            let url = if id == 0 {
                API_BASE.to_string()
            } else {
                format!("{}/{}", API_BASE, id)
            };

            wasm_bindgen_futures::spawn_local(async move {
                let changed = changed.clone();
                let on_changed = on_changed.clone();
                let req = if id == 0 {
                    Request::post(&url)
                    .json(&did)
                    .unwrap()
                } else {
                    Request::patch(&url)
                    .json(&did)
                    .unwrap()
                };
    
                req.send()
                    .await
                    .unwrap();

                changed.set(false);
                on_changed.emit(());                    
            });
        })
    };
    
     let handle_confirm = Callback::from(move |_| {
        let on_changed = on_changed.clone();
            wasm_bindgen_futures::spawn_local(async move {
                let on_changed = on_changed.clone();
                Request::delete(&format!("{}/{}",API_BASE, id))
                    .body("")                    
                    .unwrap()
                    .send()
                    .await
                    .unwrap();
                on_changed.emit(());
            })
    });

    let handle_delete: Callback<MouseEvent> = {
        let dialog_ref = dialog_ref.clone();
        Callback::from(move |_e| {
            let d = dialog_ref.cast::<HtmlDialogElement>().unwrap();
                d.show_modal().unwrap();
        })
    };

    html!{
        <tr>
            <td>
                <input type="text" 
                    class="input" 
                    value={(*did_number).to_string()}
                    id="did_number" 
                    oninput={handle_did_input.clone()}
                />
            </td>
            <td>
                <select class="select select-ghost" onchange={handle_target_type_change}>
                    <option selected={props.target_type == "Url"}>{"Url"}</option>
                    <option selected={props.target_type == "Moh"}>{"Moh"}</option>
                    <option selected={props.target_type == "NoService"}>{"NoService"}</option>
                    <option selected={props.target_type == "NightMode"}>{"NightMode"}</option>
                    <option selected={props.target_type == "ExternalNumber"}>{"ExternalNumber"}</option>
                    <option selected={props.target_type == "CustomMessage"}>{"CustomMessage"}</option>
                </select>
            </td>
            <td>
                <input type="text" 
                    class="input"
                    id="target" 
                    value={(*target).clone()}
                    oninput={handle_target_input.clone()}
                />
            </td>
            <td>
                <select class="select select-ghost" onchange={handle_trunk_change}>
                    <option selected={props.trunk == "3229"}>{"3229"}</option>
                    <option selected={props.trunk == "3401"}>{"3401"}</option>
                    <option selected={props.trunk == "413"}>{"413"}</option>
                    <option selected={props.trunk == "435"}>{"435"}</option>
                </select>
            </td>

            <td>
                <input type="checkbox" 
                    checked={*active} 
                    class="toggle"
                    id="active"
                    onchange={handle_active_change.clone()}
                />
            </td>
            <td class="flex justify-end">
                if *changed && id != 0 {
                    <button class="btn btn-primary btn-outline btn-circle" onclick={handle_save.clone()}>
                        <Icon 
                            data={IconData::LUCIDE_SAVE}
                        />
                    </button>
                }
                if id != 0 {
                    <button class="btn btn-warning btn-outline btn-circle ml-2" onclick={handle_delete}>
                        <Icon
                            data={IconData::LUCIDE_TRASH_2}
                        />
                    </button>
                }
                if id == 0 {
                    <button class="btn btn-primary btn-outline btn-circle ml-2" onclick={handle_save}>
                        <Icon
                            data={IconData::LUCIDE_PLUS}
                        />
                    </button>                    
                }                         
            </td>
            <dialog ref={dialog_ref} class="modal">
                <div class="modal-box">
                    <h3 class="font-bold text-lg">{"Warning"}</h3>
                    <p class="py-4">{format!("About to delete DID: {}", *did_number)}</p>
                    <div class="modal-action">
                        <form method="dialog">
                            <button onclick={handle_confirm} class="btn btn-warning mr-2">{"Yes"}</button>
                            <button class="btn">{"No"}</button>
                        </form>
                    </div>
                </div>
            </dialog>            
        </tr>
    }
}

#[component]
pub fn DidListComponent() -> Html {
    let changed = use_state(||0);
    let trigger = use_force_update();   
    let dids: UseStateHandle<Vec<Did>> = use_state(||vec![]);
    {
        let changed = changed.clone();
        let dids = dids.clone();
        use_effect_with(changed, move |_| {
            let dids = dids.clone();
            wasm_bindgen_futures::spawn_local(async move {
                let res = Request::get(API_BASE)
                    .send()
                    .await
                    .unwrap();

                let dids_fetched: Vec<Did> = res.json().await.unwrap();
                dids.set(dids_fetched);
            });
        });
    }
    let handle_change = Callback::from(move |()| {
        let count = *changed + 1;
        gloo_console::log!(count);
        changed.set(count);
        trigger.force_update();
        web_sys::window().unwrap().location().reload().unwrap();
    });

    html!{
        <div>
            <table class="table">
                <DidComponent 
                    did_id={0}
                    did_number={""}
                    target_type={"NoService"}
                    target={""}
                    active=true
                    trunk="3229"
                    on_changed={handle_change.clone()}
                />
            </table>
            <div class="divider"></div>
            <table class="table table-zebra">
                <thead>
                    <tr>
                        <th>{"DID number"}</th>
                        <th>{"Target type"}</th>
                        <th>{"Target"}</th>
                        <th>{"Trunk"}</th>
                        <th>{"Active"}</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                {
                    dids.iter().map(|d|{
                        html!{
                            <DidComponent 
                                did_id={d.id}
                                did_number={d.did_number.clone()}
                                target_type={d.target_type.clone()}
                                target={d.target.clone().unwrap_or_default()}
                                active ={d.active}
                                trunk = {d.trunk.clone()}
                                on_changed={handle_change.clone()}
                            />    
                        }
                    }).collect::<Html>()
                }
                </tbody>
            </table>
        </div>
    }
}