use dioxus::prelude::*;
use dioxus_free_icons::icons::bs_icons::*;
#[allow(unused_imports)]
use dioxus_free_icons::icons::bs_icons::{BsGear, BsPencil};
use dioxus_free_icons::Icon;

use crate::components::page_header::PageHeader;
use crate::components::pagination::Pagination;
use crate::components::toast::{ToastType, Toasts};
use crate::pages::graph_explorer::GraphExplorerInline;

async fn async_sleep_5s() {
    #[cfg(feature = "web")]
    {
        gloo_timers::future::TimeoutFuture::new(5_000).await;
    }
    #[cfg(not(feature = "web"))]
    {
        tokio::time::sleep(std::time::Duration::from_secs(5)).await;
    }
}

#[component]
pub fn RepositoriesPage() -> Element {
    let mut page = use_signal(|| 1u64);
    let mut show_add_form = use_signal(|| false);
    let mut name = use_signal(String::new);
    let mut git_url = use_signal(String::new);
    let mut branch = use_signal(|| "main".to_string());
    let mut auth_token = use_signal(String::new);
    let mut auth_username = use_signal(String::new);
    let mut show_auth = use_signal(|| false);
    let mut ssh_public_key = use_signal(String::new);
    let mut show_tracker = use_signal(|| false);
    let mut tracker_type_val = use_signal(String::new);
    let mut tracker_owner_val = use_signal(String::new);
    let mut tracker_repo_val = use_signal(String::new);
    let mut tracker_token_val = use_signal(String::new);
    let mut adding = use_signal(|| false);
    let mut toasts = use_context::<Toasts>();
    let mut confirm_delete = use_signal(|| Option::<(String, String)>::None); // (id, name)
    let mut edit_repo_id = use_signal(|| Option::<String>::None);
    let mut edit_name = use_signal(String::new);
    let mut edit_branch = use_signal(String::new);
    let mut edit_tracker_type = use_signal(String::new);
    let mut edit_tracker_owner = use_signal(String::new);
    let mut edit_tracker_repo = use_signal(String::new);
    let mut edit_tracker_token = use_signal(String::new);
    let mut edit_saving = use_signal(|| false);
    let mut edit_webhook_secret = use_signal(|| Option::<String>::None);
    let mut edit_webhook_tracker = use_signal(String::new);
    let mut scanning_ids = use_signal(Vec::<String>::new);
    let mut graph_repo_id = use_signal(|| Option::<String>::None);

    let mut repos = use_resource(move || {
        let p = page();
        async move {
            crate::infrastructure::repositories::fetch_repositories(p)
                .await
                .ok()
        }
    });

    rsx! {
        PageHeader {
            title: "Repositories",
            description: "Tracked git repositories",
        }

        div { style: "margin-bottom: 16px;",
            button {
                class: "btn btn-primary",
                onclick: move |_| show_add_form.toggle(),
                if show_add_form() { "Cancel" } else { "+ Add Repository" }
            }
        }

        if show_add_form() {
            div { class: "card",
                div { class: "card-header", "Add Repository" }
                div { class: "form-group",
                    label { "Name" }
                    input {
                        r#type: "text",
                        placeholder: "my-project",
                        value: "{name}",
                        oninput: move |e| name.set(e.value()),
                    }
                }
                div { class: "form-group",
                    label { "Git URL" }
                    input {
                        r#type: "text",
                        placeholder: "https://github.com/org/repo.git  or  git@github.com:org/repo.git",
                        value: "{git_url}",
                        oninput: move |e| git_url.set(e.value()),
                    }
                }
                div { class: "form-group",
                    label { "Default Branch" }
                    input {
                        r#type: "text",
                        placeholder: "main",
                        value: "{branch}",
                        oninput: move |e| branch.set(e.value()),
                    }
                }

                // Private repo auth section
                div { style: "margin-top: 8px;",
                    button {
                        class: "btn btn-ghost",
                        style: "font-size: 12px; padding: 4px 8px;",
                        onclick: move |_| {
                            let opening = !show_auth();
                            show_auth.toggle();
                            if opening {
                                // Fetch SSH key every time the section opens
                                ssh_public_key.set(String::new());
                                spawn(async move {
                                    match crate::infrastructure::repositories::fetch_ssh_public_key().await {
                                        Ok(key) => ssh_public_key.set(key),
                                        Err(_) => ssh_public_key.set("(not available)".to_string()),
                                    }
                                });
                            }
                        },
                        if show_auth() { "Hide auth options" } else { "Private repository?" }
                    }
                }

                if show_auth() {
                    div { class: "auth-section", style: "margin-top: 12px; padding: 12px; border: 1px solid var(--border-subtle); border-radius: 8px;",
                        // SSH deploy key display
                        div { style: "margin-bottom: 12px;",
                            label { style: "font-size: 12px; color: var(--text-secondary);",
                                "For SSH URLs: add this deploy key (read-only) to your repository"
                            }
                            div {
                                style: "margin-top: 4px; padding: 8px; background: var(--bg-secondary); border-radius: 4px; font-family: monospace; font-size: 11px; word-break: break-all; user-select: all;",
                                if ssh_public_key().is_empty() {
                                    "Loading..."
                                } else {
                                    "{ssh_public_key}"
                                }
                            }
                        }

                        // HTTPS auth fields
                        p { style: "font-size: 12px; color: var(--text-secondary); margin-bottom: 8px;",
                            "For HTTPS URLs: provide an access token (PAT) or username/password"
                        }
                        div { class: "form-group",
                            label { "Auth Token / Password" }
                            input {
                                r#type: "password",
                                placeholder: "ghp_xxxx or personal access token",
                                value: "{auth_token}",
                                oninput: move |e| auth_token.set(e.value()),
                            }
                        }
                        div { class: "form-group",
                            label { "Username (optional, defaults to x-access-token)" }
                            input {
                                r#type: "text",
                                placeholder: "x-access-token",
                                value: "{auth_username}",
                                oninput: move |e| auth_username.set(e.value()),
                            }
                        }
                    }
                }

                // Issue tracker config section
                div { style: "margin-top: 8px;",
                    button {
                        class: "btn btn-ghost",
                        style: "font-size: 12px; padding: 4px 8px;",
                        onclick: move |_| show_tracker.toggle(),
                        if show_tracker() { "Hide tracker options" } else { "Issue tracker?" }
                    }
                }

                if show_tracker() {
                    div { class: "auth-section", style: "margin-top: 12px; padding: 12px; border: 1px solid var(--border-subtle); border-radius: 8px;",
                        p { style: "font-size: 12px; color: var(--text-secondary); margin-bottom: 8px;",
                            "Configure an issue tracker to auto-create issues from findings"
                        }
                        div { class: "form-group",
                            label { "Tracker Type" }
                            select {
                                value: "{tracker_type_val}",
                                onchange: move |e| tracker_type_val.set(e.value()),
                                option { value: "", "None" }
                                option { value: "github", "GitHub" }
                                option { value: "gitlab", "GitLab" }
                                option { value: "gitea", "Gitea" }
                                option { value: "jira", "Jira" }
                            }
                        }
                        div { class: "form-group",
                            label { "Owner / Namespace" }
                            input {
                                r#type: "text",
                                placeholder: "org-name",
                                value: "{tracker_owner_val}",
                                oninput: move |e| tracker_owner_val.set(e.value()),
                            }
                        }
                        div { class: "form-group",
                            label { "Repository / Project" }
                            input {
                                r#type: "text",
                                placeholder: "repo-name",
                                value: "{tracker_repo_val}",
                                oninput: move |e| tracker_repo_val.set(e.value()),
                            }
                        }
                        div { class: "form-group",
                            label { "Tracker Token (PAT)" }
                            input {
                                r#type: "password",
                                placeholder: "ghp_xxxx / glpat-xxxx",
                                value: "{tracker_token_val}",
                                oninput: move |e| tracker_token_val.set(e.value()),
                            }
                        }
                    }
                }

                button {
                    class: "btn btn-primary",
                    disabled: adding(),
                    onclick: move |_| {
                        let n = name();
                        let u = git_url();
                        let b = branch();
                        let tok = {
                            let v = auth_token();
                            if v.is_empty() { None } else { Some(v) }
                        };
                        let usr = {
                            let v = auth_username();
                            if v.is_empty() { None } else { Some(v) }
                        };
                        let tt = { let v = tracker_type_val(); if v.is_empty() { None } else { Some(v) } };
                        let t_owner = { let v = tracker_owner_val(); if v.is_empty() { None } else { Some(v) } };
                        let t_repo = { let v = tracker_repo_val(); if v.is_empty() { None } else { Some(v) } };
                        let t_tok = { let v = tracker_token_val(); if v.is_empty() { None } else { Some(v) } };
                        adding.set(true);
                        spawn(async move {
                            match crate::infrastructure::repositories::add_repository(n, u, b, tok, usr, tt, t_owner, t_repo, t_tok).await {
                                Ok(_) => {
                                    toasts.push(ToastType::Success, "Repository added");
                                    repos.restart();
                                }
                                Err(e) => toasts.push(ToastType::Error, e.to_string()),
                            }
                            adding.set(false);
                        });
                        show_add_form.set(false);
                        show_auth.set(false);
                        show_tracker.set(false);
                        name.set(String::new());
                        git_url.set(String::new());
                        auth_token.set(String::new());
                        auth_username.set(String::new());
                        tracker_type_val.set(String::new());
                        tracker_owner_val.set(String::new());
                        tracker_repo_val.set(String::new());
                        tracker_token_val.set(String::new());
                    },
                    if adding() { "Validating..." } else { "Add" }
                }
            }
        }

        // ── Delete confirmation dialog ──
        if let Some((del_id, del_name)) = confirm_delete() {
            div { class: "modal-overlay",
                div { class: "modal-dialog",
                    h3 { "Delete Repository" }
                    p {
                        "Are you sure you want to delete "
                        strong { "{del_name}" }
                        "?"
                    }
                    p { class: "modal-warning",
                        "This will permanently remove all associated findings, SBOM entries, scan runs, graph data, embeddings, and CVE alerts."
                    }
                    div { class: "modal-actions",
                        button {
                            class: "btn btn-secondary",
                            onclick: move |_| confirm_delete.set(None),
                            "Cancel"
                        }
                        button {
                            class: "btn btn-danger",
                            onclick: move |_| {
                                let id = del_id.clone();
                                let name = del_name.clone();
                                confirm_delete.set(None);
                                spawn(async move {
                                    match crate::infrastructure::repositories::delete_repository(id).await {
                                        Ok(_) => {
                                            toasts.push(ToastType::Success, format!("{name} deleted"));
                                            repos.restart();
                                        }
                                        Err(e) => toasts.push(ToastType::Error, e.to_string()),
                                    }
                                });
                            },
                            "Delete"
                        }
                    }
                }
            }
        }

        // ── Edit repository dialog ──
        if let Some(eid) = edit_repo_id() {
            div { class: "modal-overlay",
                div { class: "modal-dialog",
                    h3 { "Edit Repository" }
                    div { class: "form-group",
                        label { "Name" }
                        input {
                            r#type: "text",
                            value: "{edit_name}",
                            oninput: move |e| edit_name.set(e.value()),
                        }
                    }
                    div { class: "form-group",
                        label { "Default Branch" }
                        input {
                            r#type: "text",
                            value: "{edit_branch}",
                            oninput: move |e| edit_branch.set(e.value()),
                        }
                    }
                    h4 { style: "margin-top: 16px; margin-bottom: 8px; font-size: 14px; color: var(--text-secondary);", "Issue Tracker" }
                    div { class: "form-group",
                        label { "Tracker Type" }
                        select {
                            value: "{edit_tracker_type}",
                            onchange: move |e| edit_tracker_type.set(e.value()),
                            option { value: "", "None" }
                            option { value: "github", "GitHub" }
                            option { value: "gitlab", "GitLab" }
                            option { value: "gitea", "Gitea" }
                            option { value: "jira", "Jira" }
                        }
                    }
                    div { class: "form-group",
                        label { "Owner / Namespace" }
                        input {
                            r#type: "text",
                            placeholder: "org-name",
                            value: "{edit_tracker_owner}",
                            oninput: move |e| edit_tracker_owner.set(e.value()),
                        }
                    }
                    div { class: "form-group",
                        label { "Repository / Project" }
                        input {
                            r#type: "text",
                            placeholder: "repo-name",
                            value: "{edit_tracker_repo}",
                            oninput: move |e| edit_tracker_repo.set(e.value()),
                        }
                    }
                    div { class: "form-group",
                        label { "Tracker Token (leave empty to keep existing)" }
                        input {
                            r#type: "password",
                            placeholder: "Enter new token to change",
                            value: "{edit_tracker_token}",
                            oninput: move |e| edit_tracker_token.set(e.value()),
                        }
                    }
                    // Webhook configuration section
                    if let Some(secret) = edit_webhook_secret() {
                        h4 {
                            style: "margin-top: 16px; margin-bottom: 8px; font-size: 14px; color: var(--text-secondary);",
                            "Webhook Configuration"
                        }
                        p {
                            style: "font-size: 12px; color: var(--text-secondary); margin-bottom: 8px;",
                            "Add this webhook in your repository settings to enable push-triggered scans and PR reviews."
                        }
                        div { class: "form-group",
                            label { "Webhook URL" }
                            input {
                                r#type: "text",
                                readonly: true,
                                style: "font-family: monospace; font-size: 12px;",
                                value: {
                                    #[cfg(feature = "web")]
                                    let origin = web_sys::window()
                                        .and_then(|w: web_sys::Window| w.location().origin().ok())
                                        .unwrap_or_default();
                                    #[cfg(not(feature = "web"))]
                                    let origin = String::new();
                                    format!("{origin}/webhook/{}/{eid}", edit_webhook_tracker())
                                },
                            }
                        }
                        div { class: "form-group",
                            label { "Webhook Secret" }
                            input {
                                r#type: "text",
                                readonly: true,
                                style: "font-family: monospace; font-size: 12px;",
                                value: "{secret}",
                            }
                        }
                    }
                    div { class: "modal-actions",
                        button {
                            class: "btn btn-secondary",
                            onclick: move |_| edit_repo_id.set(None),
                            "Cancel"
                        }
                        button {
                            class: "btn btn-primary",
                            disabled: edit_saving(),
                            onclick: move |_| {
                                let id = eid.clone();
                                let nm = { let v = edit_name(); if v.is_empty() { None } else { Some(v) } };
                                let br = { let v = edit_branch(); if v.is_empty() { None } else { Some(v) } };
                                let tt = { let v = edit_tracker_type(); if v.is_empty() { None } else { Some(v) } };
                                let t_owner = { let v = edit_tracker_owner(); if v.is_empty() { None } else { Some(v) } };
                                let t_repo = { let v = edit_tracker_repo(); if v.is_empty() { None } else { Some(v) } };
                                let t_tok = { let v = edit_tracker_token(); if v.is_empty() { None } else { Some(v) } };
                                edit_saving.set(true);
                                spawn(async move {
                                    match crate::infrastructure::repositories::update_repository(
                                        id, nm, br, None, None, tt, t_owner, t_repo, t_tok, None,
                                    ).await {
                                        Ok(_) => {
                                            toasts.push(ToastType::Success, "Repository updated");
                                            repos.restart();
                                        }
                                        Err(e) => toasts.push(ToastType::Error, e.to_string()),
                                    }
                                    edit_saving.set(false);
                                    edit_repo_id.set(None);
                                });
                            },
                            if edit_saving() { "Saving..." } else { "Save" }
                        }
                    }
                }
            }
        }

        match &*repos.read() {
            Some(Some(resp)) => {
                let total_pages = resp.total.unwrap_or(0).div_ceil(20).max(1);
                rsx! {
                    div { class: "card",
                        div { class: "table-wrapper",
                            table {
                                thead {
                                    tr {
                                        th { "Name" }
                                        th { "Git URL" }
                                        th { "Branch" }
                                        th { "Findings" }
                                        th { "Last Scanned" }
                                        th { "Actions" }
                                    }
                                }
                                tbody {
                                    for repo in &resp.data {
                                        {
                                            let repo_id = repo.id.as_ref().map(|id| id.to_hex()).unwrap_or_default();
                                            let repo_id_scan = repo_id.clone();
                                            let repo_id_del = repo_id.clone();
                                            let repo_id_edit = repo_id.clone();
                                            let repo_name_del = repo.name.clone();
                                            let edit_repo_data = repo.clone();
                                            let is_scanning = scanning_ids().contains(&repo_id);
                                            rsx! {
                                                tr {
                                                    td { "{repo.name}" }
                                                    td {
                                                        style: "font-size: 12px; font-family: monospace;",
                                                        "{repo.git_url}"
                                                    }
                                                    td { "{repo.default_branch}" }
                                                    td { "{repo.findings_count}" }
                                                    td {
                                                        {
                                                            let now = chrono::Utc::now();
                                                            let diff = now.signed_duration_since(repo.updated_at);
                                                            let label = if diff.num_minutes() < 1 {
                                                                "just now".to_string()
                                                            } else if diff.num_hours() < 1 {
                                                                format!("{}m ago", diff.num_minutes())
                                                            } else if diff.num_days() < 1 {
                                                                format!("{}h ago", diff.num_hours())
                                                            } else if diff.num_days() < 30 {
                                                                format!("{}d ago", diff.num_days())
                                                            } else {
                                                                repo.updated_at.format("%Y-%m-%d").to_string()
                                                            };
                                                            rsx! { span { style: "font-size: 12px;", "{label}" } }
                                                        }
                                                    }
                                                    td { style: "display: flex; gap: 4px;",
                                                        button {
                                                            class: if graph_repo_id().as_deref() == Some(repo_id.as_str()) { "btn btn-ghost btn-active" } else { "btn btn-ghost" },
                                                            title: "View graph",
                                                            onclick: {
                                                                let rid = repo_id.clone();
                                                                move |_| {
                                                                    if graph_repo_id().as_deref() == Some(rid.as_str()) {
                                                                        graph_repo_id.set(None);
                                                                    } else {
                                                                        graph_repo_id.set(Some(rid.clone()));
                                                                    }
                                                                }
                                                            },
                                                            Icon { icon: BsDiagram3, width: 16, height: 16 }
                                                        }
                                                        button {
                                                            class: "btn btn-ghost",
                                                            title: "Edit repository",
                                                            onclick: move |_| {
                                                                edit_name.set(edit_repo_data.name.clone());
                                                                edit_branch.set(edit_repo_data.default_branch.clone());
                                                                edit_tracker_type.set(
                                                                    edit_repo_data.tracker_type.as_ref().map(|t| t.to_string()).unwrap_or_default()
                                                                );
                                                                edit_tracker_owner.set(edit_repo_data.tracker_owner.clone().unwrap_or_default());
                                                                edit_tracker_repo.set(edit_repo_data.tracker_repo.clone().unwrap_or_default());
                                                                edit_tracker_token.set(String::new());
                                                                edit_webhook_secret.set(None);
                                                                edit_webhook_tracker.set(String::new());
                                                                edit_repo_id.set(Some(repo_id_edit.clone()));
                                                                // Fetch webhook config in background
                                                                let rid = repo_id_edit.clone();
                                                                spawn(async move {
                                                                    if let Ok(cfg) = crate::infrastructure::repositories::fetch_webhook_config(rid).await {
                                                                        edit_webhook_secret.set(cfg.webhook_secret);
                                                                        edit_webhook_tracker.set(cfg.tracker_type);
                                                                    }
                                                                });
                                                            },
                                                            Icon { icon: BsPencil, width: 16, height: 16 }
                                                        }
                                                        button {
                                                            class: if is_scanning { "btn btn-ghost btn-scanning" } else { "btn btn-ghost" },
                                                            title: "Trigger scan",
                                                            disabled: is_scanning,
                                                            onclick: move |_| {
                                                                let id = repo_id_scan.clone();
                                                                // Add to scanning set
                                                                let mut ids = scanning_ids();
                                                                ids.push(id.clone());
                                                                scanning_ids.set(ids);
                                                                spawn(async move {
                                                                    match crate::infrastructure::repositories::trigger_repo_scan(id.clone()).await {
                                                                        Ok(_) => {
                                                                            toasts.push(ToastType::Success, "Scan triggered");
                                                                            // Poll until scan completes
                                                                            loop {
                                                                                async_sleep_5s().await;
                                                                                match crate::infrastructure::repositories::check_repo_scanning(id.clone()).await {
                                                                                    Ok(false) => break,
                                                                                    Ok(true) => continue,
                                                                                    Err(_) => break,
                                                                                }
                                                                            }
                                                                            toasts.push(ToastType::Success, "Scan complete");
                                                                            repos.restart();
                                                                        }
                                                                        Err(e) => toasts.push(ToastType::Error, e.to_string()),
                                                                    }
                                                                    // Remove from scanning set
                                                                    let mut ids = scanning_ids();
                                                                    ids.retain(|i| i != &id);
                                                                    scanning_ids.set(ids);
                                                                });
                                                            },
                                                            if is_scanning {
                                                                span { class: "spinner" }
                                                            } else {
                                                                Icon { icon: BsPlayCircle, width: 16, height: 16 }
                                                            }
                                                        }
                                                        button {
                                                            class: "btn btn-ghost btn-ghost-danger",
                                                            title: "Delete repository",
                                                            onclick: move |_| {
                                                                confirm_delete.set(Some((repo_id_del.clone(), repo_name_del.clone())));
                                                            },
                                                            Icon { icon: BsTrash, width: 16, height: 16 }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        Pagination {
                            current_page: page(),
                            total_pages: total_pages,
                            on_page_change: move |p| page.set(p),
                        }
                    }

                    // Inline graph explorer
                    if let Some(rid) = graph_repo_id() {
                        div { class: "card", style: "margin-top: 16px;",
                            div { class: "card-header", style: "display: flex; justify-content: space-between; align-items: center;",
                                span { "Code Graph" }
                                button {
                                    class: "btn btn-sm btn-ghost",
                                    title: "Close graph",
                                    onclick: move |_| { graph_repo_id.set(None); },
                                    Icon { icon: BsX, width: 18, height: 18 }
                                }
                            }
                            GraphExplorerInline { repo_id: rid }
                        }
                    }
                }
            },
            Some(None) => rsx! {
                div { class: "card", p { "Failed to load repositories." } }
            },
            None => rsx! {
                div { class: "loading", "Loading repositories..." }
            },
        }
    }
}
