use leptos::prelude::*;
use crate::components::card::{Card, CardVariant};
use crate::components::prelude::*;
use crate::api::{get_proxy_countries, get_proxy_states, get_proxy_cities, get_proxy_asns, get_proxy_zip_codes, AuthError};
use rust_shared::repository::model::{PoolType, Country, State, City, ASN, ZipCode};
use std::collections::HashMap;
use super::proxy_params_context::{use_proxy_params, pool_type_to_string};
use leptos::task::spawn_local;

/// Helper function to convert string to PoolType
fn string_to_pool_type(pool_str: &str) -> PoolType {
    match pool_str {
        "datacenter" => PoolType::Datacenter,
        "residential" => PoolType::Residential,
        "residential_premium" => PoolType::ResidentialPremium,
        "mobile" => PoolType::Mobile,
        _ => {
            log::warn!("Unknown pool type: {}, defaulting to Datacenter", pool_str);
            PoolType::Datacenter
        }
    }
}

/// Helper function to convert string to PoolType with fallback to first available pool
fn string_to_pool_type_with_fallback(pool_str: &str, available_pools: &[PoolType]) -> PoolType {
    match pool_str {
        "datacenter" => PoolType::Datacenter,
        "residential" => PoolType::Residential,
        "residential_premium" => PoolType::ResidentialPremium,
        "mobile" => PoolType::Mobile,
        _ => {
            log::warn!("Unknown pool type: {}, using first available pool", pool_str);
            available_pools.first().copied().unwrap_or(PoolType::Datacenter)
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum LocationType {
    Country,
    State,
    City,
    ZipCode,
    IncludeAsn,
    ExcludeAsn,
}

impl LocationType {
    pub fn title(&self) -> &'static str {
        match self {
            LocationType::Country => t8s!("Country Selection"),
            LocationType::State => t8s!("State Selection"), 
            LocationType::City => t8s!("City Selection"),
            LocationType::ZipCode => t8s!("Zip Code Selection"),
            LocationType::IncludeAsn => t8s!("Include ASN Selection"),
            LocationType::ExcludeAsn => t8s!("Exclude ASN Selection"),
        }
    }

    pub fn search_placeholder(&self) -> &'static str {
        match self {
            LocationType::Country => t8s!("Search countries..."),
            LocationType::State => t8s!("Search states..."),
            LocationType::City => t8s!("Search cities..."), 
            LocationType::ZipCode => t8s!("Search zip codes..."),
            LocationType::IncludeAsn => t8s!("Search ASNs to include..."),
            LocationType::ExcludeAsn => t8s!("Search ASNs to exclude..."),
        }
    }

    pub fn empty_message(&self) -> &'static str {
        match self {
            LocationType::Country => t8s!("No countries found"),
            LocationType::State => t8s!("No states found"),
            LocationType::City => t8s!("No cities found"),
            LocationType::ZipCode => t8s!("No zip codes found"),
            LocationType::IncludeAsn => t8s!("No ASNs found"),
            LocationType::ExcludeAsn => t8s!("No ASNs found"),
        }
    }

    pub fn selected_title(&self) -> &'static str {
        match self {
            LocationType::Country => t8s!("Selected Countries"),
            LocationType::State => t8s!("Selected States"),
            LocationType::City => t8s!("Selected Cities"), 
            LocationType::ZipCode => t8s!("Selected Zip Codes"),
            LocationType::IncludeAsn => t8s!("Selected ASNs to Include"),
            LocationType::ExcludeAsn => t8s!("Selected ASNs to Exclude"),
        }
    }

    pub fn all_items_title(&self) -> &'static str {
        match self {
            LocationType::Country => t8s!("All Countries List"),
            LocationType::State => t8s!("All States List"),
            LocationType::City => t8s!("All Cities List"),
            LocationType::ZipCode => t8s!("All Zip Codes List"),
            LocationType::IncludeAsn => t8s!("All ASNs List"),
            LocationType::ExcludeAsn => t8s!("All ASNs List"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct LocationItem {
    pub code: String,
    pub name: String,
    pub count: Option<u32>,
}

impl LocationItem {
    pub fn new(code: &str, name: &str, count: Option<u32>, ) -> Self {
        Self {
            code: code.to_string(),
            name: name.to_string(),
            count,
        }
    }
}




/// Dynamic location selection page that fetches data from API
#[component]
pub fn DynamicLocationSelectionPage(
    location_type: LocationType,
    on_back: Callback<()>,
    #[prop(default = "dynamic-location-selection-page")] id: &'static str,
) -> impl IntoView {
    let params_context = use_proxy_params();
    let parameters = params_context.parameters;
    
    let loading = RwSignal::new(true);
    let error = RwSignal::new(None::<String>);
    let items = RwSignal::new(Vec::<LocationItem>::new());
    
    let selected_items = RwSignal::new(match location_type {
        LocationType::Country => parameters.with(|p| p.countries.clone()),
        LocationType::State => parameters.with(|p| p.states.clone()),
        LocationType::City => parameters.with(|p| p.cities.clone()),
        LocationType::ZipCode => parameters.with(|p| p.zip_codes.clone()),
        LocationType::IncludeAsn => parameters.with(|p| p.asn_include.clone()),
        LocationType::ExcludeAsn => parameters.with(|p| p.asn_exclude.clone()),
    });
    
    let pool = move || {
        parameters.with(|p| p.pool_type.clone())
    };
    
    let location_type_for_fetch = location_type.clone();
    let location_type_for_save = location_type.clone();
    let _location_type_for_main = location_type.clone();
    let location_type_for_title = location_type.clone();
    let location_type_for_content = location_type.clone();
    
    let fetch_data = move || {
        let location_type = location_type_for_fetch.clone();
        let pool = pool();
        let parameters = parameters.clone();

        let proxies_text = t8s!("proxies");
        let failed_to_load_text = t8s!("Failed to load");
        
        spawn_local(async move {
            loading.set(true);
            error.set(None);
            
            let result = match location_type {
                LocationType::Country => {
                    get_proxy_countries(string_to_pool_type(pool_type_to_string(&pool))).await
                        .map(|countries| countries.into_iter().map(|c| LocationItem {
                            code: c.code,
                            name: c.name,
                            count: Some(c.count),
                        }).collect())
                },
                LocationType::State => {
                    let countries = parameters.with(|p| {
                        p.countries.iter().map(|code| Country {
                            code: code.clone(),
                            name: String::new(), // Name not needed for API call
                            count: 0,
                        }).collect()
                    });
                    get_proxy_states(string_to_pool_type(pool_type_to_string(&pool)), countries).await
                        .map(|states| states.into_iter().map(|s| LocationItem {
                            code: s.code,
                            name: s.name,
                            count: Some(s.count),
                        }).collect())
                },
                LocationType::City => {
                    let countries = parameters.with(|p| {
                        p.countries.iter().map(|code| Country {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    let states = parameters.with(|p| {
                        p.states.iter().map(|code| State {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    get_proxy_cities(string_to_pool_type(pool_type_to_string(&pool)), countries, states).await
                        .map(|cities| cities.into_iter().map(|c| LocationItem {
                            code: c.code,
                            name: c.name,
                            count: Some(c.count),
                        }).collect())
                },
                LocationType::IncludeAsn | LocationType::ExcludeAsn => {
                    let countries = parameters.with(|p| {
                        p.countries.iter().map(|code| Country {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    let states = parameters.with(|p| {
                        p.states.iter().map(|code| State {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    let cities = parameters.with(|p| {
                        p.cities.iter().map(|code| City {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    get_proxy_asns(string_to_pool_type(pool_type_to_string(&pool)), countries, states, cities).await
                        .map(|asns| asns.into_iter().map(|a| LocationItem {
                            code: a.code,
                            name: a.name,
                            count: Some(a.count),
                        }).collect())
                },
                LocationType::ZipCode => {
                    let countries = parameters.with(|p| {
                        p.countries.iter().map(|code| Country {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    let states = parameters.with(|p| {
                        p.states.iter().map(|code| State {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    let asns = parameters.with(|p| {
                        p.asn_include.iter().map(|code| ASN {
                            code: code.clone(),
                            name: String::new(),
                            count: 0,
                        }).collect()
                    });
                    get_proxy_zip_codes(string_to_pool_type(pool_type_to_string(&pool)), countries, states, asns).await
                        .map(|zip_codes| zip_codes.into_iter().map(|z| LocationItem {
                            code: z.code,
                            name: z.name,
                            count: Some(z.count),
                        }).collect())
                },
            };
            
            match result {
                Ok(data) => {
                    items.set(data);
                    error.set(None);
                },
                Err(e) => {
                    error.set(Some(format!("{} {}: {}", failed_to_load_text, location_type.title(), e)));
                    items.set(Vec::new());
                }
            }
            
            loading.set(false);
        });
    };
    
    let fetch_data_for_effect = fetch_data.clone();
    let fetch_data_for_error = fetch_data.clone();
    
    Effect::new(move |_| {
        fetch_data_for_effect();
    });
    
    let loading_view = move || {
        loading.get().then(|| view! {
            <div class="flex items-center justify-center h-64" id="loading-state">
                <div class="text-[rgba(255,249,247,0.6)]">{t8s!("Loading...")}</div>
            </div>
        })
    };
    
    let error_view = move || {
        error.get().map(|err| {
            let fetch_data = fetch_data_for_error.clone();
            view! {
                <div class="flex items-center justify-center h-64" id="error-state">
                    <div class="text-red-400 text-center">
                        <div class="font-semibold mb-2">{t8s!("Error")}</div>
                        <div class="text-sm">{err}</div>
                        <button 
                            class="mt-4 px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
                            on:click=move |_| fetch_data()
                        >
                            {t8s!("Retry")}
                        </button>
                    </div>
                </div>
            }
        })
    };
    
    let on_back_with_save = Callback::new(move |_| {
        let current_selection = selected_items.get();
        match location_type_for_save {
            LocationType::Country => {
                params_context.update_countries.run(current_selection);
            },
            LocationType::State => {
                params_context.update_states.run(current_selection);
            },
            LocationType::City => {
                params_context.update_cities.run(current_selection);
            },
            LocationType::ZipCode => {
                params_context.update_zip_codes.run(current_selection);
            },
            LocationType::IncludeAsn => {
                params_context.update_asn_include.run(current_selection);
            },
            LocationType::ExcludeAsn => {
                params_context.update_asn_exclude.run(current_selection);
            },
        }
        on_back.run(());
    });

    let search_term = RwSignal::new(String::new());
    
    let filtered_items = move || {
        let term = search_term.get().to_lowercase();
        let all_items = items.get();
        if term.is_empty() {
            all_items
        } else {
            all_items
                .iter()
                .filter(|item| {
                    item.name.to_lowercase().contains(&term) || 
                    item.code.to_lowercase().contains(&term)
                })
                .cloned()
                .collect()
        }
    };

    let remove_item = move |item_code: String| {
        selected_items.update(|items| {
            items.retain(|code| code != &item_code);
        });
    };

    let add_item = move |item_code: String| {
        selected_items.update(|items| {
            if !items.contains(&item_code) {
                items.push(item_code);
            }
        });
    };

    let main_content = move || {
        let location_type_for_content = location_type_for_content.clone();
        (!loading.get() && error.get().is_none()).then(move || view! {
            <div class="w-full h-full flex flex-col" id="main-content">
                <div class="flex justify-between items-center p-[14px] gap-2 mx-4 mt-4 bg-[rgba(255,249,247,0.05)] rounded-[10px]" id="search-input">
                    <input 
                        type="text"
                        placeholder=location_type_for_content.search_placeholder()
                        class="flex-1 bg-transparent text-[rgba(255,249,247,0.8)] placeholder:text-[rgba(255,249,247,0.4)] font-semibold text-base leading-[22px] tracking-[-0.02em] outline-none"
                        prop:value=move || search_term.get()
                        on:input=move |ev| {
                            search_term.set(event_target_value(&ev));
                        }
                        id="location-search"
                    />
                </div>

                <div class="flex flex-col gap-3 p-4" id="selected-items-section">
                    <h3 class="font-bold text-xs leading-[18px] tracking-[-0.02em] uppercase text-[rgba(255,249,247,0.4)]" id="selected-title">
                        {location_type_for_content.selected_title()}
                    </h3>
                    <div class="flex flex-wrap items-center gap-2" id="selected-items-container">
                        {move || {
                            selected_items.with(move |selected_codes| {
                                let all_items = items.get();
                                selected_codes.iter().enumerate().map(|(index, code)| {
                                    let item = all_items.iter().find(|i| &i.code == code);
                                    let item_name = item.map(|i| i.name.clone()).unwrap_or_else(|| code.clone());
                                    let code_clone = code.clone();
                                    
                                    view! {
                                        <div 
                                            class="flex justify-center items-center pl-2 pr-1 gap-1 h-[30px] bg-[rgba(255,249,247,0.05)] rounded-md"
                                            id=format!("selected-item-{}", index)
                                        >
                                            <span 
                                                class="font-semibold text-base leading-[22px] text-center tracking-[-0.02em] text-[rgba(255,249,247,0.95)]"
                                                id=format!("selected-item-name-{}", index)
                                            >
                                                {item_name}
                                            </span>
                                            <button 
                                                class="w-[22px] h-[22px] flex items-center justify-center"
                                                id=format!("remove-item-{}", index)
                                                on:click=move |_| {
                                                    remove_item(code_clone.clone());
                                                }
                                            >
                                                <svg 
                                                    width="22" 
                                                    height="22" 
                                                    viewBox="0 0 22 22" 
                                                    fill="none" 
                                                    xmlns="http://www.w3.org/2000/svg"
                                                    class="w-full h-full"
                                                >
                                                    <path 
                                                        d="M18 6L6 18M6 6L18 18" 
                                                        stroke="rgba(255,249,247,0.4)" 
                                                        stroke-width="2" 
                                                        stroke-linecap="round" 
                                                        stroke-linejoin="round"
                                                    />
                                                </svg>
                                            </button>
                                        </div>
                                    }
                                }).collect::<Vec<_>>()
                            })
                        }}
                        
                        <button 
                            class="w-[38px] h-[38px] bg-[rgba(255,249,247,0.05)] rounded-[10px] flex items-center justify-center"
                            id="clear-all-button"
                            on:click=move |_| {
                                selected_items.set(vec![]);
                            }
                        >
                            <svg 
                                width="24" 
                                height="24" 
                                viewBox="0 0 24 24" 
                                fill="none" 
                                xmlns="http://www.w3.org/2000/svg"
                                class="w-[24px] h-[24px]"
                            >
                                <path 
                                    d="M18 6L6 18M6 6L18 18" 
                                    stroke="rgba(255,249,247,0.4)" 
                                    stroke-width="2" 
                                    stroke-linecap="round" 
                                    stroke-linejoin="round"
                                />
                            </svg>
                        </button>
                    </div>
                </div>

                <div class="px-4" id="all-items-header">
                    <h3 class="font-bold text-xs leading-[18px] tracking-[-0.02em] uppercase text-[rgba(255,249,247,0.4)]" id="all-items-title">
                        {location_type_for_content.all_items_title()}
                    </h3>
                </div>

                <div class="flex p-4 pt-2 gap-4 flex-1 overflow-hidden" id="items-container">
                    <div class="flex flex-col gap-2 flex-1 h-full bg-[rgba(255,249,247,0.05)] rounded-[14px] p-4 overflow-y-auto" id="items-list-container">
                        {move || {
                            let items_list = filtered_items();
                            let selected_codes = selected_items.get();
                            
                            if items_list.is_empty() {
                                view! {
                                    <div class="flex items-center justify-center h-full text-[rgba(255,249,247,0.4)]" id="empty-message">
                                        {location_type_for_content.empty_message()}
                                    </div>
                                }.into_any()
                            } else {
                                items_list.iter().enumerate().map(|(index, item)| {
                                    let is_selected = selected_codes.contains(&item.code);
                                    let item_clone = item.clone();
                                    
                                    view! {
                                        <button 
                                            class="flex justify-between items-center px-4 py-[14px] gap-2 w-full h-[52px] bg-[rgba(255,249,247,0.05)] rounded-[14px] hover:bg-[rgba(255,249,247,0.08)] transition-colors duration-200"
                                            id=format!("item-entry-{}", index)
                                            on:click=move |_| {
                                                if is_selected {
                                                    remove_item(item_clone.code.clone());
                                                } else {
                                                    add_item(item_clone.code.clone());
                                                }
                                            }
                                        >
                                            <div class="flex items-center gap-2" id=format!("item-info-{}", index)>
                                                <span 
                                                    class="font-semibold text-lg leading-6 tracking-[-0.02em] text-[rgba(255,249,247,0.6)]"
                                                    id=format!("item-name-{}", index)
                                                >
                                                    {item.name.clone()}
                                                </span>
                                            </div>
                                            {item.count.map(|count| view! {
                                                <span 
                                                    class="font-semibold text-lg leading-6 tracking-[-0.02em] text-[rgba(255,249,247,0.6)]"
                                                    id=format!("item-count-{}", index)
                                                >
                                                    {count.to_string()}
                                                </span>
                                            })}
                                        </button>
                                    }
                                }).collect::<Vec<_>>().into_any()
                            }
                        }}
                    </div>
                </div>
            </div>
        })
    };
    
    view! {
        <div 
            class="w-full h-full flex flex-col"
            id=id
        >
            <Card 
                variant=CardVariant::L2
                max_width="w-full" 
                padding="p-0" 
                class="w-full flex-1 overflow-hidden relative"
                id="dynamic-location-selection-main-card"
            >
                <div class="flex items-center gap-2 px-4 h-[56px] bg-[rgba(255,249,247,0.05)] backdrop-blur-[100px] rounded-t-[18px]" id="dynamic-location-header">
                    <button 
                        class="w-[22px] h-[22px] flex items-center justify-center"
                        id="dynamic-back-button"
                        on:click=move |_| {
                            on_back_with_save.run(());
                        }
                    >
                        <svg 
                            width="22" 
                            height="22" 
                            viewBox="0 0 22 22" 
                            fill="none" 
                            xmlns="http://www.w3.org/2000/svg"
                            class="w-full h-full"
                        >
                            <path 
                                d="M19 11H5M12 18L5 11L12 4" 
                                stroke="rgba(255,249,247,0.4)" 
                                stroke-width="2" 
                                stroke-linecap="round" 
                                stroke-linejoin="round"
                            />
                        </svg>
                    </button>
                    <h1 class="font-semibold text-lg leading-6 tracking-[-0.02em] text-[rgba(255,249,247,0.95)]" id="dynamic-location-title">
                        {location_type_for_title.title()}
                    </h1>
                </div>

                <div class="flex-1 overflow-hidden" id="dynamic-content-area">
                    {loading_view}
                    {error_view}
                    {main_content}
                </div>
            </Card>
        </div>
    }
}
