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

use crate::app::Route;
use crate::infrastructure::pentest::{
    export_pentest_report, fetch_attack_chain, fetch_pentest_findings, fetch_pentest_messages,
    fetch_pentest_session, send_pentest_message,
};

#[component]
pub fn PentestSessionPage(session_id: String) -> Element {
    let sid = session_id.clone();
    let sid_for_session = session_id.clone();
    let sid_for_findings = session_id.clone();
    let sid_for_chain = session_id.clone();

    let mut session = use_resource(move || {
        let id = sid_for_session.clone();
        async move { fetch_pentest_session(id).await.ok() }
    });
    let mut messages_res = use_resource(move || {
        let id = sid.clone();
        async move { fetch_pentest_messages(id).await.ok() }
    });
    let mut findings = use_resource(move || {
        let id = sid_for_findings.clone();
        async move { fetch_pentest_findings(id).await.ok() }
    });
    let mut attack_chain = use_resource(move || {
        let id = sid_for_chain.clone();
        async move { fetch_attack_chain(id).await.ok() }
    });

    let mut input_text = use_signal(String::new);
    let mut sending = use_signal(|| false);
    let mut right_tab = use_signal(|| "findings".to_string());
    let mut chain_view = use_signal(|| "graph".to_string()); // "graph" or "list"
    let mut exporting = use_signal(|| false);

    // Auto-poll messages every 3s when session is running
    let session_status = {
        let s = session.read();
        match &*s {
            Some(Some(resp)) => resp
                .data
                .get("status")
                .and_then(|v| v.as_str())
                .unwrap_or("unknown")
                .to_string(),
            _ => "unknown".to_string(),
        }
    };

    let is_running = session_status == "running";

    let sid_for_poll = session_id.clone();
    use_effect(move || {
        if is_running {
            let _sid = sid_for_poll.clone();
            spawn(async move {
                #[cfg(feature = "web")]
                gloo_timers::future::TimeoutFuture::new(3_000).await;
                #[cfg(not(feature = "web"))]
                tokio::time::sleep(std::time::Duration::from_secs(3)).await;
                messages_res.restart();
                findings.restart();
                attack_chain.restart();
                session.restart();
            });
        }
    });

    // Load attack chain into vis-network when data changes and graph tab is active
    let chain_data_for_viz = attack_chain.read().clone();
    let current_tab = right_tab.read().clone();
    let current_chain_view = chain_view.read().clone();
    use_effect(move || {
        if current_tab == "chain" && current_chain_view == "graph" {
            if let Some(Some(data)) = &chain_data_for_viz {
                if !data.data.is_empty() {
                    let nodes_json =
                        serde_json::to_string(&data.data).unwrap_or_else(|_| "[]".to_string());
                    let js = format!(
                        r#"if (window.__loadAttackChain) {{ window.__loadAttackChain({nodes_json}); }}"#
                    );
                    document::eval(&js);
                }
            }
        }
    });

    // Send message handler
    let sid_for_send = session_id.clone();
    let mut do_send = move || {
        let text = input_text.read().trim().to_string();
        if text.is_empty() || *sending.read() {
            return;
        }
        let sid = sid_for_send.clone();
        input_text.set(String::new());
        sending.set(true);
        spawn(async move {
            let _ = send_pentest_message(sid, text).await;
            sending.set(false);
            messages_res.restart();
        });
    };

    let mut do_send_click = do_send.clone();

    // Export handler
    let sid_for_export = session_id.clone();
    let do_export_md = move |_| {
        let sid = sid_for_export.clone();
        exporting.set(true);
        spawn(async move {
            match export_pentest_report(sid.clone(), "markdown".to_string()).await {
                Ok(content) => {
                    // Trigger download via JS
                    let escaped = content
                        .replace('\\', "\\\\")
                        .replace('`', "\\`")
                        .replace("${", "\\${");
                    let js = format!(
                        r#"
                        var blob = new Blob([`{escaped}`], {{ type: 'text/markdown' }});
                        var url = URL.createObjectURL(blob);
                        var a = document.createElement('a');
                        a.href = url;
                        a.download = 'pentest-report-{sid}.md';
                        document.body.appendChild(a);
                        a.click();
                        document.body.removeChild(a);
                        URL.revokeObjectURL(url);
                        "#
                    );
                    document::eval(&js);
                }
                Err(e) => {
                    tracing::warn!("Export failed: {e}");
                }
            }
            exporting.set(false);
        });
    };

    let sid_for_export_json = session_id.clone();
    let do_export_json = move |_| {
        let sid = sid_for_export_json.clone();
        exporting.set(true);
        spawn(async move {
            match export_pentest_report(sid.clone(), "json".to_string()).await {
                Ok(content) => {
                    let escaped = content
                        .replace('\\', "\\\\")
                        .replace('`', "\\`")
                        .replace("${", "\\${");
                    let js = format!(
                        r#"
                        var blob = new Blob([`{escaped}`], {{ type: 'application/json' }});
                        var url = URL.createObjectURL(blob);
                        var a = document.createElement('a');
                        a.href = url;
                        a.download = 'pentest-report-{sid}.json';
                        document.body.appendChild(a);
                        a.click();
                        document.body.removeChild(a);
                        URL.revokeObjectURL(url);
                        "#
                    );
                    document::eval(&js);
                }
                Err(e) => {
                    tracing::warn!("Export failed: {e}");
                }
            }
            exporting.set(false);
        });
    };

    // Session header info
    let target_name = {
        let s = session.read();
        match &*s {
            Some(Some(resp)) => resp
                .data
                .get("target_name")
                .and_then(|v| v.as_str())
                .unwrap_or("Pentest Session")
                .to_string(),
            _ => "Pentest Session".to_string(),
        }
    };

    let strategy = {
        let s = session.read();
        match &*s {
            Some(Some(resp)) => resp
                .data
                .get("strategy")
                .and_then(|v| v.as_str())
                .unwrap_or("-")
                .to_string(),
            _ => "-".to_string(),
        }
    };

    let header_tool_count = {
        let s = session.read();
        match &*s {
            Some(Some(resp)) => resp
                .data
                .get("tool_invocations")
                .and_then(|v| v.as_u64())
                .unwrap_or(0),
            _ => 0,
        }
    };

    let header_findings_count = {
        let f = findings.read();
        match &*f {
            Some(Some(data)) => data.total.unwrap_or(0),
            _ => 0,
        }
    };

    let status_style = match session_status.as_str() {
        "running" => "background: #16a34a; color: #fff;",
        "completed" => "background: #2563eb; color: #fff;",
        "failed" => "background: #dc2626; color: #fff;",
        "paused" => "background: #d97706; color: #fff;",
        _ => "background: var(--bg-tertiary); color: var(--text-secondary);",
    };

    rsx! {
        div { class: "back-nav",
            Link {
                to: Route::PentestDashboardPage {},
                class: "btn btn-ghost btn-back",
                Icon { icon: BsArrowLeft, width: 16, height: 16 }
                "Back to Pentest Dashboard"
            }
        }

        // Session header
        div { style: "display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; flex-wrap: wrap; gap: 8px;",
            div {
                h2 { style: "margin: 0 0 4px 0;", "{target_name}" }
                div { style: "display: flex; gap: 8px; align-items: center; flex-wrap: wrap;",
                    span { class: "badge", style: "{status_style}", "{session_status}" }
                    span { class: "badge", style: "background: var(--bg-tertiary); color: var(--text-secondary);",
                        "{strategy}"
                    }
                }
            }
            div { style: "display: flex; gap: 8px; align-items: center;",
                // Export buttons
                div { style: "display: flex; gap: 4px;",
                    button {
                        class: "btn btn-ghost",
                        style: "font-size: 0.8rem; padding: 4px 10px;",
                        disabled: *exporting.read(),
                        onclick: do_export_md,
                        Icon { icon: BsFileEarmarkText, width: 12, height: 12 }
                        " Export MD"
                    }
                    button {
                        class: "btn btn-ghost",
                        style: "font-size: 0.8rem; padding: 4px 10px;",
                        disabled: *exporting.read(),
                        onclick: do_export_json,
                        Icon { icon: BsFiletypeJson, width: 12, height: 12 }
                        " Export JSON"
                    }
                }
                div { style: "display: flex; gap: 16px; font-size: 0.85rem; color: var(--text-secondary);",
                    span {
                        Icon { icon: BsWrench, width: 14, height: 14 }
                        " {header_tool_count} tools"
                    }
                    span {
                        Icon { icon: BsShieldExclamation, width: 14, height: 14 }
                        " {header_findings_count} findings"
                    }
                }
            }
        }

        // Split layout: chat left, findings/chain right
        div { style: "display: grid; grid-template-columns: 1fr 420px; gap: 16px; height: calc(100vh - 220px); min-height: 400px;",

            // Left: Chat area
            div { class: "card", style: "display: flex; flex-direction: column; overflow: hidden;",
                div { class: "card-header", style: "flex-shrink: 0;", "Chat" }

                // Messages
                div {
                    style: "flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px;",
                    match &*messages_res.read() {
                        Some(Some(data)) => {
                            let msgs = &data.data;
                            if msgs.is_empty() {
                                rsx! {
                                    div { style: "text-align: center; color: var(--text-secondary); padding: 32px;",
                                        h3 { style: "margin-bottom: 8px;", "Start the conversation" }
                                        p { "Send a message to guide the pentest agent." }
                                    }
                                }
                            } else {
                                rsx! {
                                    for (i, msg) in msgs.iter().enumerate() {
                                        {
                                            let role = msg.get("role").and_then(|v| v.as_str()).unwrap_or("assistant").to_string();
                                            let content = msg.get("content").and_then(|v| v.as_str()).unwrap_or("").to_string();
                                            let msg_type = msg.get("type").and_then(|v| v.as_str()).unwrap_or("text").to_string();
                                            let tool_name = msg.get("tool_name").and_then(|v| v.as_str()).unwrap_or("").to_string();
                                            let tool_status = msg.get("tool_status").and_then(|v| v.as_str()).unwrap_or("").to_string();

                                            if msg_type == "tool_call" || msg_type == "tool_result" {
                                                let tool_icon_style = match tool_status.as_str() {
                                                    "success" => "color: #16a34a;",
                                                    "error" => "color: #dc2626;",
                                                    "running" => "color: #d97706;",
                                                    _ => "color: var(--text-secondary);",
                                                };
                                                rsx! {
                                                    div {
                                                        key: "{i}",
                                                        style: "display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--bg-tertiary); border-radius: 6px; font-size: 0.8rem; color: var(--text-secondary);",
                                                        span { style: "{tool_icon_style}",
                                                            Icon { icon: BsWrench, width: 12, height: 12 }
                                                        }
                                                        span { style: "font-family: monospace;", "{tool_name}" }
                                                        if !tool_status.is_empty() {
                                                            span { class: "badge", style: "font-size: 0.7rem;", "{tool_status}" }
                                                        }
                                                        if !content.is_empty() {
                                                            details { style: "margin-left: auto; cursor: pointer;",
                                                                summary { style: "font-size: 0.75rem;", "details" }
                                                                pre { style: "margin-top: 4px; padding: 8px; background: var(--bg-primary); border-radius: 4px; font-size: 0.75rem; overflow-x: auto; max-height: 200px; white-space: pre-wrap;",
                                                                    "{content}"
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            } else if role == "user" {
                                                rsx! {
                                                    div {
                                                        key: "{i}",
                                                        style: "display: flex; justify-content: flex-end;",
                                                        div {
                                                            style: "max-width: 80%; padding: 10px 14px; background: #2563eb; color: #fff; border-radius: 12px 12px 2px 12px; font-size: 0.9rem; line-height: 1.5; white-space: pre-wrap;",
                                                            "{content}"
                                                        }
                                                    }
                                                }
                                            } else {
                                                rsx! {
                                                    div {
                                                        key: "{i}",
                                                        style: "display: flex; gap: 8px; align-items: flex-start;",
                                                        div {
                                                            style: "flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%; background: var(--bg-tertiary); display: flex; align-items: center; justify-content: center;",
                                                            Icon { icon: BsCpu, width: 14, height: 14 }
                                                        }
                                                        div {
                                                            style: "max-width: 80%; padding: 10px 14px; background: var(--bg-tertiary); border-radius: 12px 12px 12px 2px; font-size: 0.9rem; line-height: 1.5; white-space: pre-wrap;",
                                                            "{content}"
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        Some(None) => rsx! { p { style: "padding: 16px; color: var(--text-secondary);", "Failed to load messages." } },
                        None => rsx! { p { style: "padding: 16px; color: var(--text-secondary);", "Loading messages..." } },
                    }

                    if *sending.read() {
                        div { style: "display: flex; gap: 8px; align-items: flex-start;",
                            div {
                                style: "flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%; background: var(--bg-tertiary); display: flex; align-items: center; justify-content: center;",
                                Icon { icon: BsCpu, width: 14, height: 14 }
                            }
                            div {
                                style: "padding: 10px 14px; background: var(--bg-tertiary); border-radius: 12px 12px 12px 2px; font-size: 0.9rem; color: var(--text-secondary);",
                                "Thinking..."
                            }
                        }
                    }
                }

                // Input area
                div { style: "flex-shrink: 0; padding: 12px; border-top: 1px solid var(--border-color); display: flex; gap: 8px;",
                    textarea {
                        class: "chat-input",
                        style: "flex: 1;",
                        placeholder: "Guide the pentest agent...",
                        value: "{input_text}",
                        oninput: move |e| input_text.set(e.value()),
                        onkeydown: move |e: Event<KeyboardData>| {
                            if e.key() == Key::Enter && !e.modifiers().shift() {
                                e.prevent_default();
                                do_send();
                            }
                        },
                    }
                    button {
                        class: "btn btn-primary",
                        style: "align-self: flex-end;",
                        disabled: *sending.read(),
                        onclick: move |_| do_send_click(),
                        "Send"
                    }
                }
            }

            // Right: Findings / Attack Chain tabs
            div { class: "card", style: "display: flex; flex-direction: column; overflow: hidden;",
                // Tab bar
                div { style: "display: flex; border-bottom: 1px solid var(--border-color); flex-shrink: 0;",
                    button {
                        style: if *right_tab.read() == "findings" {
                            "flex: 1; padding: 10px; background: none; border: none; border-bottom: 2px solid #2563eb; color: var(--text-primary); cursor: pointer; font-weight: 600;"
                        } else {
                            "flex: 1; padding: 10px; background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-secondary); cursor: pointer;"
                        },
                        onclick: move |_| right_tab.set("findings".to_string()),
                        Icon { icon: BsShieldExclamation, width: 14, height: 14 }
                        " Findings ({header_findings_count})"
                    }
                    button {
                        style: if *right_tab.read() == "chain" {
                            "flex: 1; padding: 10px; background: none; border: none; border-bottom: 2px solid #2563eb; color: var(--text-primary); cursor: pointer; font-weight: 600;"
                        } else {
                            "flex: 1; padding: 10px; background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-secondary); cursor: pointer;"
                        },
                        onclick: move |_| right_tab.set("chain".to_string()),
                        Icon { icon: BsDiagram3, width: 14, height: 14 }
                        " Attack Chain"
                    }
                }

                // Tab content
                div { style: "flex: 1; overflow-y: auto; display: flex; flex-direction: column;",
                    if *right_tab.read() == "findings" {
                        // Findings tab
                        div { style: "padding: 12px; flex: 1; overflow-y: auto;",
                            match &*findings.read() {
                                Some(Some(data)) => {
                                    let finding_list = &data.data;
                                    if finding_list.is_empty() {
                                        rsx! {
                                            div { style: "text-align: center; color: var(--text-secondary); padding: 24px;",
                                                p { "No findings yet." }
                                            }
                                        }
                                    } else {
                                        rsx! {
                                            div { style: "display: flex; flex-direction: column; gap: 8px;",
                                                for finding in finding_list {
                                                    {
                                                        let title = finding.get("title").and_then(|v| v.as_str()).unwrap_or("Untitled").to_string();
                                                        let severity = finding.get("severity").and_then(|v| v.as_str()).unwrap_or("info").to_string();
                                                        let vuln_type = finding.get("vuln_type").and_then(|v| v.as_str()).unwrap_or("-").to_string();
                                                        let endpoint = finding.get("endpoint").and_then(|v| v.as_str()).unwrap_or("").to_string();
                                                        let exploitable = finding.get("exploitable").and_then(|v| v.as_bool()).unwrap_or(false);
                                                        let sev_style = match severity.as_str() {
                                                            "critical" => "background: #dc2626; color: #fff;",
                                                            "high" => "background: #ea580c; color: #fff;",
                                                            "medium" => "background: #d97706; color: #fff;",
                                                            "low" => "background: #2563eb; color: #fff;",
                                                            _ => "background: var(--bg-tertiary); color: var(--text-secondary);",
                                                        };
                                                        rsx! {
                                                            div { style: "padding: 10px; background: var(--bg-tertiary); border-radius: 8px;",
                                                                div { style: "display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px;",
                                                                    span { style: "font-weight: 600; font-size: 0.85rem;", "{title}" }
                                                                    div { style: "display: flex; gap: 4px;",
                                                                        if exploitable {
                                                                            span { class: "badge", style: "background: #dc2626; color: #fff; font-size: 0.7rem;", "Exploitable" }
                                                                        }
                                                                        span { class: "badge", style: "{sev_style}", "{severity}" }
                                                                    }
                                                                }
                                                                div { style: "font-size: 0.8rem; color: var(--text-secondary);", "{vuln_type}" }
                                                                if !endpoint.is_empty() {
                                                                    div { style: "font-size: 0.75rem; color: var(--text-secondary); font-family: monospace; margin-top: 2px;",
                                                                        "{endpoint}"
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                Some(None) => rsx! { p { style: "color: var(--text-secondary); padding: 12px;", "Failed to load findings." } },
                                None => rsx! { p { style: "color: var(--text-secondary); padding: 12px;", "Loading..." } },
                            }
                        }
                    } else {
                        // Attack chain tab — graph/list toggle
                        div { style: "display: flex; gap: 4px; padding: 8px 12px; flex-shrink: 0;",
                            button {
                                class: if *chain_view.read() == "graph" { "btn btn-primary" } else { "btn btn-ghost" },
                                style: "font-size: 0.75rem; padding: 3px 8px;",
                                onclick: move |_| chain_view.set("graph".to_string()),
                                Icon { icon: BsDiagram3, width: 12, height: 12 }
                                " Graph"
                            }
                            button {
                                class: if *chain_view.read() == "list" { "btn btn-primary" } else { "btn btn-ghost" },
                                style: "font-size: 0.75rem; padding: 3px 8px;",
                                onclick: move |_| chain_view.set("list".to_string()),
                                Icon { icon: BsListOl, width: 12, height: 12 }
                                " List"
                            }
                        }

                        if *chain_view.read() == "graph" {
                            // Interactive DAG visualization
                            div { style: "flex: 1; position: relative; min-height: 300px;",
                                div {
                                    id: "attack-chain-canvas",
                                    style: "width: 100%; height: 100%; position: absolute; inset: 0;",
                                }
                                match &*attack_chain.read() {
                                    Some(Some(data)) if data.data.is_empty() => rsx! {
                                        div { style: "position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--text-secondary);",
                                            p { "No attack chain steps yet." }
                                        }
                                    },
                                    _ => rsx! {},
                                }
                            }
                        } else {
                            // List view
                            div { style: "flex: 1; overflow-y: auto; padding: 0 12px 12px;",
                                match &*attack_chain.read() {
                                    Some(Some(data)) => {
                                        let steps = &data.data;
                                        if steps.is_empty() {
                                            rsx! {
                                                div { style: "text-align: center; color: var(--text-secondary); padding: 24px;",
                                                    p { "No attack chain steps yet." }
                                                }
                                            }
                                        } else {
                                            rsx! {
                                                div { style: "display: flex; flex-direction: column; gap: 4px;",
                                                    for (i, step) in steps.iter().enumerate() {
                                                        {
                                                            let tool_name = step.get("tool_name").and_then(|v| v.as_str()).unwrap_or("Step").to_string();
                                                            let step_status = step.get("status").and_then(|v| v.as_str()).unwrap_or("pending").to_string();
                                                            let reasoning = step.get("llm_reasoning").and_then(|v| v.as_str()).unwrap_or("").to_string();
                                                            let findings_count = step.get("findings_produced").and_then(|v| v.as_array()).map(|a| a.len()).unwrap_or(0);
                                                            let risk_score = step.get("risk_score").and_then(|v| v.as_u64());
                                                            let step_num = i + 1;
                                                            let dot_color = match step_status.as_str() {
                                                                "completed" => "#16a34a",
                                                                "running" => "#d97706",
                                                                "failed" => "#dc2626",
                                                                "skipped" => "#374151",
                                                                _ => "var(--text-secondary)",
                                                            };
                                                            rsx! {
                                                                div { style: "display: flex; gap: 10px; padding: 8px 0;",
                                                                    div { style: "display: flex; flex-direction: column; align-items: center;",
                                                                        div { style: "width: 10px; height: 10px; border-radius: 50%; background: {dot_color}; flex-shrink: 0;" }
                                                                        if i < steps.len() - 1 {
                                                                            div { style: "width: 2px; flex: 1; background: var(--border-color); margin-top: 4px;" }
                                                                        }
                                                                    }
                                                                    div { style: "flex: 1; min-width: 0;",
                                                                        div { style: "display: flex; justify-content: space-between; align-items: center;",
                                                                            span { style: "font-size: 0.85rem; font-weight: 600;",
                                                                                "{step_num}. {tool_name}"
                                                                            }
                                                                            div { style: "display: flex; gap: 4px;",
                                                                                if findings_count > 0 {
                                                                                    span { class: "badge", style: "font-size: 0.65rem; background: #dc2626; color: #fff;",
                                                                                        "{findings_count} findings"
                                                                                    }
                                                                                }
                                                                                if let Some(score) = risk_score {
                                                                                    span { class: "badge", style: "font-size: 0.65rem;",
                                                                                        "risk: {score}"
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                        if !reasoning.is_empty() {
                                                                            div { style: "font-size: 0.8rem; color: var(--text-secondary); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;",
                                                                                "{reasoning}"
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    Some(None) => rsx! { p { style: "color: var(--text-secondary); padding: 12px;", "Failed to load attack chain." } },
                                    None => rsx! { p { style: "color: var(--text-secondary); padding: 12px;", "Loading..." } },
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
