use dioxus::prelude::*;
use dioxus_free_icons::icons::bs_icons::*;
use dioxus_free_icons::Icon;

use crate::app::Route;
use crate::components::page_header::PageHeader;
use crate::components::pagination::Pagination;
use crate::components::severity_badge::SeverityBadge;

#[component]
pub fn FindingsPage() -> Element {
    let mut page = use_signal(|| 1u64);
    let mut severity_filter = use_signal(String::new);
    let mut type_filter = use_signal(String::new);
    let mut status_filter = use_signal(String::new);
    let mut repo_filter = use_signal(String::new);
    let mut search_query = use_signal(String::new);
    let mut sort_by = use_signal(|| "created_at".to_string());
    let mut sort_order = use_signal(|| "desc".to_string());
    let mut selected_ids = use_signal(Vec::<String>::new);

    let repos = use_resource(|| async {
        crate::infrastructure::onboarding::fetch_targets()
            .await
            .ok()
    });

    let mut findings = use_resource(move || {
        let query = crate::infrastructure::findings::FindingsQuery {
            page: page(),
            severity: severity_filter(),
            scan_type: type_filter(),
            status: status_filter(),
            repo_id: repo_filter(),
            q: search_query(),
            sort_by: sort_by(),
            sort_order: sort_order(),
        };
        async move {
            crate::infrastructure::findings::fetch_findings(query)
                .await
                .ok()
        }
    });

    let toggle_sort = move |field: &'static str| {
        move |_: MouseEvent| {
            if sort_by() == field {
                sort_order.set(if sort_order() == "asc" {
                    "desc".to_string()
                } else {
                    "asc".to_string()
                });
            } else {
                sort_by.set(field.to_string());
                sort_order.set("desc".to_string());
            }
            page.set(1);
        }
    };

    let sort_indicator = move |field: &str| -> String {
        if sort_by() == field {
            if sort_order() == "asc" {
                " \u{25B2}".to_string()
            } else {
                " \u{25BC}".to_string()
            }
        } else {
            String::new()
        }
    };

    rsx! {
        PageHeader {
            title: "Findings",
            description: "Security and compliance findings across all repositories",
        }

        div { class: "filter-bar",
            input {
                r#type: "text",
                placeholder: "Search findings...",
                style: "min-width: 200px;",
                oninput: move |e| { search_query.set(e.value()); page.set(1); },
            }
            select {
                onchange: move |e| { repo_filter.set(e.value()); page.set(1); },
                option { value: "", "All Targets" }
                {
                    match &*repos.read() {
                        Some(Some(resp)) => rsx! {
                            for t in &resp.data {
                                {
                                    let id = t.get("_id").and_then(|o| o.get("$oid")).and_then(|s| s.as_str()).unwrap_or_default().to_string();
                                    let name = t.get("name").and_then(|n| n.as_str()).unwrap_or_default().to_string();
                                    rsx! {
                                        option { value: "{id}", "{name}" }
                                    }
                                }
                            }
                        },
                        _ => rsx! {},
                    }
                }
            }
            select {
                onchange: move |e| { severity_filter.set(e.value()); page.set(1); },
                option { value: "", "All Severities" }
                option { value: "critical", "Critical" }
                option { value: "high", "High" }
                option { value: "medium", "Medium" }
                option { value: "low", "Low" }
                option { value: "info", "Info" }
            }
            select {
                onchange: move |e| { type_filter.set(e.value()); page.set(1); },
                option { value: "", "All Types" }
                option { value: "sast", "SAST" }
                option { value: "sbom", "SBOM" }
                option { value: "cve", "CVE" }
                option { value: "gdpr", "GDPR" }
                option { value: "oauth", "OAuth" }
                option { value: "secret_detection", "Secrets" }
                option { value: "lint", "Lint" }
            }
            select {
                onchange: move |e| { status_filter.set(e.value()); page.set(1); },
                option { value: "", "All Statuses" }
                option { value: "open", "Open" }
                option { value: "triaged", "Triaged" }
                option { value: "resolved", "Resolved" }
                option { value: "false_positive", "False Positive" }
                option { value: "ignored", "Ignored" }
            }
        }

        // Bulk action bar
        if !selected_ids().is_empty() {
            div {
                class: "card",
                style: "display: flex; align-items: center; gap: 12px; padding: 12px 16px; margin-bottom: 16px; background: rgba(56, 189, 248, 0.08); border-color: rgba(56, 189, 248, 0.2);",
                span {
                    style: "font-size: 14px; color: var(--text-secondary);",
                    "{selected_ids().len()} selected"
                }
                for status in ["triaged", "resolved", "false_positive", "ignored"] {
                    {
                        let status_str = status.to_string();
                        let label = match status {
                            "false_positive" => "False Positive",
                            other => {
                                // Capitalize first letter
                                let mut s = other.to_string();
                                if let Some(c) = s.get_mut(0..1) { c.make_ascii_uppercase(); }
                                // Leak to get a &str that lives long enough - this is fine for static-ish UI strings
                                &*Box::leak(s.into_boxed_str())
                            }
                        };
                        rsx! {
                            button {
                                class: "btn btn-sm btn-ghost",
                                title: "Mark {label}",
                                onclick: move |_| {
                                    let ids = selected_ids();
                                    let s = status_str.clone();
                                    spawn(async move {
                                        let _ = crate::infrastructure::findings::bulk_update_finding_status(ids, s).await;
                                        findings.restart();
                                    });
                                    selected_ids.set(Vec::new());
                                },
                                match status {
                                    "triaged" => rsx! { Icon { icon: BsEye, width: 14, height: 14 } },
                                    "resolved" => rsx! { Icon { icon: BsCheckCircle, width: 14, height: 14 } },
                                    "false_positive" => rsx! { Icon { icon: BsXCircle, width: 14, height: 14 } },
                                    "ignored" => rsx! { Icon { icon: BsDashCircle, width: 14, height: 14 } },
                                    _ => rsx! {},
                                }
                                " {label}"
                            }
                        }
                    }
                }
                button {
                    class: "btn btn-sm btn-ghost",
                    onclick: move |_| { selected_ids.set(Vec::new()); },
                    "Clear"
                }
            }
        }

        match &*findings.read() {
            Some(Some(resp)) => {
                let total_pages = resp.total.unwrap_or(0).div_ceil(20).max(1);
                let all_ids: Vec<String> = resp.data.iter().filter_map(|f| f.id.as_ref().map(|id| id.to_hex())).collect();
                rsx! {
                    div { class: "card",
                        div { class: "table-wrapper",
                            table {
                                thead {
                                    tr {
                                        th {
                                            style: "width: 40px;",
                                            input {
                                                r#type: "checkbox",
                                                checked: !all_ids.is_empty() && selected_ids().len() == all_ids.len(),
                                                onchange: move |_| {
                                                    if selected_ids().len() == all_ids.len() {
                                                        selected_ids.set(Vec::new());
                                                    } else {
                                                        selected_ids.set(all_ids.clone());
                                                    }
                                                },
                                            }
                                        }
                                        th {
                                            style: "cursor: pointer; user-select: none;",
                                            onclick: toggle_sort("severity"),
                                            "Severity{sort_indicator(\"severity\")}"
                                        }
                                        th {
                                            style: "cursor: pointer; user-select: none;",
                                            onclick: toggle_sort("title"),
                                            "Title{sort_indicator(\"title\")}"
                                        }
                                        th {
                                            style: "cursor: pointer; user-select: none;",
                                            onclick: toggle_sort("scan_type"),
                                            "Type{sort_indicator(\"scan_type\")}"
                                        }
                                        th { "Scanner" }
                                        th { "File" }
                                        th {
                                            style: "cursor: pointer; user-select: none;",
                                            onclick: toggle_sort("status"),
                                            "Status{sort_indicator(\"status\")}"
                                        }
                                    }
                                }
                                tbody {
                                    for finding in &resp.data {
                                        {
                                            let id = finding.id.as_ref().map(|id| id.to_hex()).unwrap_or_default();
                                            let id_for_check = id.clone();
                                            let is_selected = selected_ids().contains(&id);
                                            rsx! {
                                                tr {
                                                    td {
                                                        input {
                                                            r#type: "checkbox",
                                                            checked: is_selected,
                                                            onchange: move |_| {
                                                                let mut ids = selected_ids();
                                                                if ids.contains(&id_for_check) {
                                                                    ids.retain(|i| i != &id_for_check);
                                                                } else {
                                                                    ids.push(id_for_check.clone());
                                                                }
                                                                selected_ids.set(ids);
                                                            },
                                                        }
                                                    }
                                                    td { SeverityBadge { severity: finding.severity.to_string() } }
                                                    td {
                                                        Link {
                                                            to: Route::FindingDetailPage { id },
                                                            style: "color: var(--accent); text-decoration: none;",
                                                            "{finding.title}"
                                                        }
                                                    }
                                                    td { "{finding.scan_type}" }
                                                    td {
                                                        Icon { icon: BsCpu, width: 14, height: 14 }
                                                        " {finding.scanner}"
                                                    }
                                                    td {
                                                        style: "font-family: monospace; font-size: 12px;",
                                                        Icon { icon: BsFileEarmarkCode, width: 14, height: 14 }
                                                        " {finding.file_path.as_deref().unwrap_or(\"-\")}"
                                                    }
                                                    td {
                                                        span { class: "badge badge-info",
                                                            {
                                                                use compliance_core::models::FindingStatus;
                                                                match &finding.status {
                                                                    FindingStatus::Open => rsx! { Icon { icon: BsCircle, width: 12, height: 12 } },
                                                                    FindingStatus::Triaged => rsx! { Icon { icon: BsEye, width: 12, height: 12 } },
                                                                    FindingStatus::Resolved => rsx! { Icon { icon: BsCheckCircle, width: 12, height: 12 } },
                                                                    FindingStatus::FalsePositive => rsx! { Icon { icon: BsXCircle, width: 12, height: 12 } },
                                                                    FindingStatus::Ignored => rsx! { Icon { icon: BsDashCircle, width: 12, height: 12 } },
                                                                }
                                                            }
                                                            " {finding.status}"
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        Pagination {
                            current_page: page(),
                            total_pages: total_pages,
                            on_page_change: move |p| page.set(p),
                        }
                    }
                }
            },
            Some(None) => rsx! {
                div { class: "card", p { "Failed to load findings." } }
            },
            None => rsx! {
                div { class: "loading", "Loading findings..." }
            },
        }
    }
}
