use super::common;
use crate::{Message, SoftwareApp, ICON_SIZE_CARD};
use cosmic::iced::{Alignment, Length};
use cosmic::{theme, widget, Element};
use rakuos_packages::NativeApp;

const WEBAPP_CATEGORIES: &[&str] = &[
    "Network",
    "Office",
    "Utility",
    "AudioVideo",
    "Education",
    "Game",
    "Graphics",
    "Science",
];

pub fn view(app: &SoftwareApp, width: usize) -> Element<'_, Message> {
    if app.loading {
        return common::loading_page("Loading web apps...");
    }

    let spacing = theme::active().cosmic().spacing;
    let mut column = widget::column::with_capacity(4)
        .padding([0, spacing.space_s, spacing.space_m, spacing.space_s])
        .spacing(spacing.space_xs)
        .width(Length::Fill);

    let total = app.webapp_catalog.len();
    let visible = app.webapp_visible_count.min(total);

    column = column.push(
        widget::row::with_children(vec![
            widget::column::with_children(vec![
                widget::text::title2("Web Apps").into(),
                widget::text::caption("Install curated websites as desktop apps.").into(),
            ])
            .width(Length::Fill)
            .into(),
            widget::text::caption(if total == 0 {
                String::new()
            } else if visible < total {
                format!("{visible} of {total} available")
            } else {
                format!("{total} available")
            })
            .into(),
            widget::button::suggested("Add Custom")
                .on_press(Message::OpenCustomWebApp)
                .into(),
        ])
        .spacing(spacing.space_s)
        .align_y(Alignment::Center),
    );

    if total == 0 {
        column = column.push(widget::text::body(if app.status.is_empty() {
            "No web apps available."
        } else {
            &app.status
        }));
    } else {
        column = column.push(webapp_grid(&app.webapp_catalog[..visible], width));
        if visible < total {
            column = column.push(
                widget::button::standard(format!("Load more ({visible}/{total})"))
                    .on_press(Message::LoadMoreApps),
            );
        }
    }

    column.into()
}

pub(crate) fn custom_webapp_popup(app: &SoftwareApp) -> Element<'static, Message> {
    let spacing = theme::active().cosmic().spacing;

    widget::container(
        widget::column::with_children(vec![
            widget::row::with_children(vec![
                widget::text::title3("Add Custom Web App").into(),
                widget::space::horizontal().width(Length::Fill).into(),
                widget::button::icon(widget::icon::from_name("window-close-symbolic"))
                    .on_press(Message::CloseCustomWebApp)
                    .into(),
            ])
            .align_y(Alignment::Center)
            .into(),
            widget::text::caption("App Name *").into(),
            widget::text_input::text_input("My App", app.webapp_custom_name.clone())
                .on_input(Message::CustomWebAppNameChanged)
                .into(),
            widget::text::caption("URL *").into(),
            widget::text_input::text_input("https://example.com", app.webapp_custom_url.clone())
                .on_input(Message::CustomWebAppUrlChanged)
                .into(),
            widget::text::caption("Description").into(),
            widget::text_input::text_input("Optional description", app.webapp_custom_description.clone())
                .on_input(Message::CustomWebAppDescriptionChanged)
                .into(),
            widget::text::caption("Menu Category").into(),
            category_grid(&app.webapp_custom_category),
            widget::text::caption("Icon file path or URL").into(),
            widget::row::with_children(vec![
                widget::text_input::text_input("/path/to/icon.png or https://...", app.webapp_custom_icon_source.clone())
                    .on_input(Message::CustomWebAppIconSourceChanged)
                    .into(),
                widget::button::standard("Browse...")
                    .on_press(Message::BrowseCustomWebAppIcon)
                    .into(),
            ])
            .spacing(spacing.space_xs)
            .align_y(Alignment::Center)
            .into(),
            if app.webapp_custom_status.is_empty() {
                widget::space::vertical().height(Length::Fixed(1.0)).into()
            } else {
                widget::text::caption(app.webapp_custom_status.clone()).into()
            },
            widget::row::with_children(vec![
                widget::button::standard("Cancel")
                    .on_press(Message::CloseCustomWebApp)
                    .into(),
                widget::space::horizontal().width(Length::Fill).into(),
                if app.webapp_custom_running {
                    widget::button::standard("Adding...")
                        .into()
                } else {
                    widget::button::suggested("Add Web App")
                        .on_press(Message::AddCustomWebApp)
                        .into()
                },
            ])
            .align_y(Alignment::Center)
            .into(),
        ])
        .spacing(spacing.space_s)
        .width(Length::Fill),
    )
    .padding(spacing.space_m)
    .class(theme::Container::Dialog)
    .width(Length::Fixed(560.0))
    .into()
}

fn category_grid(active_category: &str) -> Element<'static, Message> {
    let spacing = theme::active().cosmic().spacing;
    let mut grid = widget::grid();
    let mut col = 0;

    for category in WEBAPP_CATEGORIES {
        if col >= 4 {
            grid = grid.insert_row();
            col = 0;
        }

        let button: Element<_> = if active_category == *category {
            widget::button::suggested(*category)
                .width(Length::Fill)
                .on_press(Message::CustomWebAppCategoryChanged((*category).to_string()))
                .into()
        } else {
            widget::button::standard(*category)
                .width(Length::Fill)
                .on_press(Message::CustomWebAppCategoryChanged((*category).to_string()))
                .into()
        };

        grid = grid.push(button);
        col += 1;
    }

    grid.column_spacing(spacing.space_xxs)
        .row_spacing(spacing.space_xxs)
        .into()
}

fn webapp_grid(apps: &[NativeApp], width: usize) -> Element<'_, Message> {
    let spacing = theme::active().cosmic().spacing;
    let GridMetrics {
        cols,
        item_width,
        column_spacing,
    } = GridMetrics::new(width, 120, spacing.space_s);

    let mut grid = widget::grid();
    let mut col = 0;
    for app in apps {
        if col >= cols {
            grid = grid.insert_row();
            col = 0;
        }
        grid = grid.push(
            widget::mouse_area(webapp_card(app, item_width))
                .on_press(Message::SelectInstalledApp(app.clone())),
        );
        col += 1;
    }

    grid.column_spacing(column_spacing)
        .row_spacing(column_spacing)
        .into()
}

fn webapp_card(app: &NativeApp, width: usize) -> Element<'_, Message> {
    let spacing = theme::active().cosmic().spacing;
    let status = if app.installed { "Installed" } else { "" };

    widget::container(
        widget::column::with_children(vec![
            common::app_icon(&app.icon_path, &app.icon_url, ICON_SIZE_CARD),
            widget::text::caption(&app.name)
                .height(Length::Fixed(30.0))
                .into(),
            widget::text::caption(status)
                .height(Length::Fixed(16.0))
                .into(),
        ])
            .spacing(spacing.space_xxs)
            .align_x(Alignment::Center),
    )
    .align_x(Alignment::Center)
    .align_y(Alignment::Center)
    .width(Length::Fixed(width as f32))
    .height(Length::Fixed(132.0))
    .padding(spacing.space_xs)
    .class(theme::Container::Card)
    .into()
}

struct GridMetrics {
    cols: usize,
    item_width: usize,
    column_spacing: u16,
}

impl GridMetrics {
    fn new(width: usize, min_width: usize, column_spacing: u16) -> Self {
        let width_m1 = width.saturating_sub(min_width);
        let cols_m1 = width_m1 / (min_width + column_spacing as usize);
        let cols = cols_m1 + 1;
        let item_width = width
            .saturating_sub(cols_m1 * column_spacing as usize)
            .checked_div(cols)
            .unwrap_or(min_width);
        Self {
            cols,
            item_width,
            column_spacing,
        }
    }
}
