use ely_browser_core::{BrowserSnapshot, InstalledPlugin};
use ely_design_system::colors;
use ely_domain::{PluginId, PluginManifest, PluginPermission, PluginPermissionRisk, ProfileKind};
use gpui::prelude::FluentBuilder;
use gpui::{AnyElement, Context, IntoElement, ParentElement, Styled, div, px, rgb};
use gpui_component::{
    IconName, Sizable, StyledExt,
    button::{Button, ButtonVariants},
    scroll::ScrollableElement,
};

use super::{ElyShell, render_canvas_surface};

impl ElyShell {
    pub(super) fn render_plugin_detail_page(
        &mut self,
        snapshot: &BrowserSnapshot,
        route: &str,
        cx: &mut Context<Self>,
    ) -> AnyElement {
        let plugin_id = parse_plugin_detail_route(route);
        let plugin =
            plugin_id.as_ref().and_then(|plugin_id| find_installed_plugin(snapshot, plugin_id));

        render_canvas_surface(
            div()
                .size_full()
                .p_8()
                .flex()
                .flex_col()
                .gap_5()
                .when_some(plugin, |this, plugin| {
                    this.child(self.render_plugin_detail_header(
                        plugin,
                        &snapshot.active_profile_kind,
                        cx,
                    ))
                    .child(render_plugin_security_summary(plugin))
                    .child(render_plugin_manifest_rows(plugin.manifest()))
                    .child(render_plugin_permission_list(plugin.manifest()))
                })
                .when(plugin.is_none(), |this| {
                    this.child(render_missing_plugin_detail(plugin_id.as_ref(), cx))
                }),
        )
    }

    fn render_plugin_detail_header(
        &mut self,
        plugin: &InstalledPlugin,
        profile_kind: &ProfileKind,
        cx: &mut Context<Self>,
    ) -> AnyElement {
        let plugin_id = plugin.id().clone();
        let target_enabled = !plugin.enabled();
        let private_allowed = plugin.private_window_allowed();
        let status_label = plugin_status_label(plugin, profile_kind);
        let status_color =
            if plugin.enabled_for_profile(profile_kind) { colors::SUCCESS } else { colors::MUTED };
        let action_label = if plugin.enabled() { "Disable" } else { "Enable" };
        let action_icon = if plugin.enabled() { IconName::CircleX } else { IconName::Check };
        let private_action_label = if private_allowed { "Block Private" } else { "Allow Private" };
        let private_action_icon = if private_allowed { IconName::CircleX } else { IconName::Check };

        div()
            .flex()
            .items_end()
            .justify_between()
            .gap_4()
            .child(
                div()
                    .min_w_0()
                    .flex()
                    .flex_col()
                    .gap_2()
                    .child(
                        div()
                            .text_size(px(26.0))
                            .truncate()
                            .text_color(rgb(colors::INK))
                            .child(plugin.manifest().name().to_string()),
                    )
                    .child(div().text_sm().truncate().text_color(rgb(colors::MUTED)).child(
                        format!("{} - {}", plugin.manifest().author(), plugin.id().as_str()),
                    )),
            )
            .child(
                div()
                    .flex()
                    .items_center()
                    .gap_3()
                    .text_xs()
                    .child(div().font_semibold().text_color(rgb(status_color)).child(status_label))
                    .child(
                        Button::new("toggle-plugin-detail-private")
                            .ghost()
                            .xsmall()
                            .icon(private_action_icon)
                            .label(private_action_label)
                            .tooltip("Set Private Window Permission")
                            .on_click(cx.listener({
                                let plugin_id = plugin_id.clone();
                                move |shell, _, _, cx| {
                                    shell.set_plugin_private_window_allowed(
                                        plugin_id.clone(),
                                        !private_allowed,
                                        cx,
                                    );
                                }
                            })),
                    )
                    .child(
                        Button::new("toggle-plugin-detail-enabled")
                            .xsmall()
                            .icon(action_icon)
                            .label(action_label)
                            .tooltip("Set Plugin State")
                            .on_click(cx.listener(move |shell, _, _, cx| {
                                shell.set_plugin_enabled(plugin_id.clone(), target_enabled, cx);
                            })),
                    )
                    .child(
                        Button::new("open-plugin-settings")
                            .ghost()
                            .xsmall()
                            .icon(IconName::Info)
                            .label("Settings")
                            .tooltip("Open Plugin Settings")
                            .on_click(cx.listener(|shell, _, window, cx| {
                                shell.open_internal_tab("ely://settings/plugins", window, cx);
                            })),
                    ),
            )
            .into_any_element()
    }
}

fn plugin_status_label(plugin: &InstalledPlugin, profile_kind: &ProfileKind) -> &'static str {
    if !plugin.enabled() {
        return "Disabled";
    }
    match profile_kind {
        ProfileKind::Standard => "Enabled",
        ProfileKind::Private if plugin.private_window_allowed() => "Private Enabled",
        ProfileKind::Private => "Private Off",
    }
}

fn render_plugin_security_summary(plugin: &InstalledPlugin) -> AnyElement {
    let manifest = plugin.manifest();
    div()
        .border_t_1()
        .border_b_1()
        .border_color(rgb(colors::HAIRLINE))
        .py_3()
        .flex()
        .items_center()
        .justify_between()
        .gap_4()
        .children([
            detail_metric("Signature", manifest.signature().algorithm().as_str()),
            detail_metric("Key", manifest.signature().key_id()),
            detail_metric("High Risk", manifest.high_risk_permissions().count().to_string()),
            detail_metric("Sync", sync_participation_label(manifest)),
        ])
        .into_any_element()
}

fn detail_metric(label: &'static str, value: impl Into<String>) -> AnyElement {
    div()
        .min_w_0()
        .flex()
        .flex_col()
        .gap_1()
        .child(div().text_xs().text_color(rgb(colors::MUTED)).child(label))
        .child(
            div()
                .text_sm()
                .font_semibold()
                .truncate()
                .text_color(rgb(colors::INK))
                .child(value.into()),
        )
        .into_any_element()
}

fn render_plugin_manifest_rows(manifest: &PluginManifest) -> AnyElement {
    div()
        .flex()
        .flex_col()
        .border_b_1()
        .border_color(rgb(colors::HAIRLINE))
        .child(plugin_detail_row(
            IconName::Info,
            "Description",
            manifest.description(),
            "Manifest summary",
        ))
        .child(plugin_detail_row(IconName::User, "Author", manifest.author(), "Publisher"))
        .child(plugin_detail_row(IconName::Globe, "Homepage", manifest.homepage(), "Publisher URL"))
        .child(plugin_detail_row(
            IconName::CircleCheck,
            "Minimum Build",
            manifest.min_ely_build().to_string(),
            "Required ELY version",
        ))
        .child(plugin_detail_row(
            IconName::BookOpen,
            "Checksum",
            manifest.checksum(),
            "Wasm package checksum",
        ))
        .into_any_element()
}

fn plugin_detail_row(
    icon: IconName,
    label: &'static str,
    value: impl Into<String>,
    detail: &'static str,
) -> AnyElement {
    let value = value.into();

    div()
        .py_3()
        .border_t_1()
        .border_color(rgb(colors::HAIRLINE))
        .flex()
        .items_center()
        .justify_between()
        .gap_4()
        .child(
            div()
                .min_w_0()
                .flex()
                .items_center()
                .gap_3()
                .child(div().text_color(rgb(colors::MUTED_SOFT)).child(icon))
                .child(
                    div()
                        .min_w_0()
                        .flex()
                        .flex_col()
                        .gap_1()
                        .child(
                            div()
                                .text_sm()
                                .font_semibold()
                                .truncate()
                                .text_color(rgb(colors::INK))
                                .child(label),
                        )
                        .child(div().text_xs().text_color(rgb(colors::MUTED)).child(detail)),
                ),
        )
        .child(
            div()
                .max_w(px(380.0))
                .truncate()
                .text_sm()
                .font_semibold()
                .text_color(rgb(colors::INK))
                .child(value),
        )
        .into_any_element()
}

fn render_plugin_permission_list(manifest: &PluginManifest) -> AnyElement {
    if manifest.permissions().is_empty() {
        return div()
            .text_sm()
            .text_color(rgb(colors::MUTED))
            .child("This plugin declares no permissions.")
            .into_any_element();
    }

    div()
        .flex_1()
        .min_h_0()
        .flex()
        .flex_col()
        .gap_3()
        .child(div().text_xs().font_semibold().text_color(rgb(colors::MUTED)).child("Permissions"))
        .child(
            div()
                .flex_1()
                .min_h_0()
                .flex()
                .flex_col()
                .overflow_y_scrollbar()
                .children(manifest.permissions().iter().map(render_permission_row)),
        )
        .into_any_element()
}

fn render_permission_row(permission: &PluginPermission) -> AnyElement {
    let risk = permission.risk();
    let risk_color = match risk {
        PluginPermissionRisk::Standard => colors::MUTED,
        PluginPermissionRisk::High => colors::ERROR,
    };

    div()
        .py_3()
        .border_b_1()
        .border_color(rgb(colors::HAIRLINE))
        .flex()
        .items_center()
        .justify_between()
        .gap_4()
        .child(
            div()
                .min_w_0()
                .flex()
                .items_center()
                .gap_3()
                .child(div().text_color(rgb(risk_color)).child(permission_icon(permission)))
                .child(
                    div()
                        .min_w_0()
                        .flex()
                        .flex_col()
                        .gap_1()
                        .child(
                            div()
                                .text_sm()
                                .font_semibold()
                                .truncate()
                                .text_color(rgb(colors::INK))
                                .child(permission.as_str()),
                        )
                        .child(
                            div()
                                .text_xs()
                                .text_color(rgb(colors::MUTED))
                                .child(permission_scope_label(permission)),
                        ),
                ),
        )
        .child(
            div()
                .text_xs()
                .font_semibold()
                .text_color(rgb(risk_color))
                .child(permission_risk_label(risk)),
        )
        .into_any_element()
}

fn render_missing_plugin_detail(
    plugin_id: Option<&PluginId>,
    cx: &mut Context<ElyShell>,
) -> AnyElement {
    let detail = plugin_id
        .map(|plugin_id| plugin_id.as_str().to_string())
        .unwrap_or_else(|| "Invalid plugin route".to_string());

    div()
        .size_full()
        .flex()
        .flex_col()
        .gap_5()
        .child(
            div()
                .flex()
                .flex_col()
                .gap_2()
                .child(
                    div().text_size(px(26.0)).text_color(rgb(colors::INK)).child("Plugin Details"),
                )
                .child(div().text_sm().text_color(rgb(colors::MUTED)).child(detail)),
        )
        .child(
            div()
                .border_t_1()
                .border_color(rgb(colors::HAIRLINE))
                .pt_5()
                .flex()
                .items_center()
                .justify_between()
                .gap_4()
                .child(
                    div()
                        .text_sm()
                        .text_color(rgb(colors::MUTED))
                        .child("Plugin details are available for installed plugins."),
                )
                .child(
                    Button::new("open-plugin-marketplace")
                        .primary()
                        .small()
                        .icon(IconName::ExternalLink)
                        .label("Open Plugins")
                        .tooltip("Open Plugin Marketplace")
                        .on_click(cx.listener(|shell, _, window, cx| {
                            shell.open_internal_tab("ely://plugins", window, cx);
                        })),
                ),
        )
        .into_any_element()
}

fn parse_plugin_detail_route(route: &str) -> Option<PluginId> {
    let plugin_id = route.strip_prefix("ely://plugin/")?;
    PluginId::parse(plugin_id).ok()
}

fn find_installed_plugin<'a>(
    snapshot: &'a BrowserSnapshot,
    plugin_id: &PluginId,
) -> Option<&'a InstalledPlugin> {
    snapshot.installed_plugins.iter().find(|plugin| plugin.id() == plugin_id)
}

fn sync_participation_label(manifest: &PluginManifest) -> &'static str {
    if manifest
        .permissions()
        .iter()
        .any(|permission| matches!(permission, PluginPermission::SyncPlugin))
    {
        "Participates"
    } else {
        "Local"
    }
}

fn permission_risk_label(risk: PluginPermissionRisk) -> &'static str {
    match risk {
        PluginPermissionRisk::Standard => "Standard",
        PluginPermissionRisk::High => "High",
    }
}

fn permission_icon(permission: &PluginPermission) -> IconName {
    if permission.requires_separate_confirmation() {
        IconName::TriangleAlert
    } else {
        IconName::CircleCheck
    }
}

fn permission_scope_label(permission: &PluginPermission) -> &'static str {
    match permission {
        PluginPermission::TabsRead => "Reads tab metadata.",
        PluginPermission::TabsWrite => "Creates, moves, or closes tabs.",
        PluginPermission::SpacesRead => "Reads Space metadata.",
        PluginPermission::SpacesWrite => "Creates or changes Spaces.",
        PluginPermission::BookmarksRead => "Reads bookmarks.",
        PluginPermission::BookmarksWrite => "Writes bookmarks.",
        PluginPermission::HistoryRead => "Reads browsing history.",
        PluginPermission::DownloadsRead => "Reads download entries.",
        PluginPermission::DownloadsWrite => "Controls downloads.",
        PluginPermission::PageMetadata => "Reads active page metadata.",
        PluginPermission::PageScreenshot => "Captures page screenshots.",
        PluginPermission::PageScript => "Runs scoped page scripts.",
        PluginPermission::ClipboardRead => "Reads clipboard content.",
        PluginPermission::ClipboardWrite => "Writes clipboard content.",
        PluginPermission::FilesystemRead => "Reads user-selected files.",
        PluginPermission::FilesystemWrite => "Writes user-selected files.",
        PluginPermission::NetworkFetch => "Performs plugin network requests.",
        PluginPermission::SettingsRead => "Reads plugin settings.",
        PluginPermission::SettingsWrite => "Writes plugin settings.",
        PluginPermission::SyncPlugin => "Syncs plugin configuration.",
        PluginPermission::UiPanel => "Registers sidebar panels.",
        PluginPermission::UiCommand => "Registers command bar actions.",
        PluginPermission::UiContextMenu => "Registers context menu actions.",
    }
}
