use crate::components::keyboard;
use iced::widget::{Space, column, container, row, scrollable, text, tooltip};
use iced::{Alignment, Background, Color, Element, Length, Theme};

use bds_core::i18n::UiLocale;

use crate::app::Message;
use crate::components::inputs;
use crate::i18n::{t, tw};
use crate::state::tabs::{Tab, TabType};

#[derive(Debug, Clone)]
pub struct DashboardStats {
    pub total_posts: usize,
    pub published_count: usize,
    pub draft_count: usize,
    pub archived_count: usize,
    pub media_count: usize,
    pub image_count: usize,
    pub total_media_size: String,
    pub tag_count: usize,
    pub category_count: usize,
}

#[derive(Debug, Clone)]
pub struct DashboardTimelineMonth {
    pub label: String,
    pub year: i32,
    pub count: usize,
}

#[derive(Debug, Clone)]
pub struct DashboardTag {
    pub name: String,
    pub count: usize,
    pub color: Option<String>,
    /// 11–22 px, scaled relative to the min/max counts of the displayed tags.
    pub font_size: f32,
}

#[derive(Debug, Clone)]
pub struct DashboardCategory {
    pub name: String,
    pub count: usize,
}

#[derive(Debug, Clone)]
pub struct DashboardRecentPost {
    pub post_id: String,
    pub title: String,
    pub status: String,
    pub date: String,
}

/// Dashboard overview state.
#[derive(Debug, Clone)]
pub struct DashboardState {
    pub title: String,
    pub subtitle: String,
    pub stats: DashboardStats,
    pub timeline: Vec<DashboardTimelineMonth>,
    pub tag_cloud: Vec<DashboardTag>,
    pub category_cloud: Vec<DashboardCategory>,
    pub recent_posts: Vec<DashboardRecentPost>,
}

impl DashboardState {
    pub fn new(project_name: String) -> Self {
        Self {
            title: t(UiLocale::En, "dashboard.overview"),
            subtitle: project_name,
            stats: DashboardStats {
                total_posts: 0,
                published_count: 0,
                draft_count: 0,
                archived_count: 0,
                media_count: 0,
                image_count: 0,
                total_media_size: "0 B".to_string(),
                tag_count: 0,
                category_count: 0,
            },
            timeline: Vec::new(),
            tag_cloud: Vec::new(),
            category_cloud: Vec::new(),
            recent_posts: Vec::new(),
        }
    }
}

/// Render the dashboard overview.
pub fn view<'a>(state: &'a DashboardState, locale: UiLocale) -> Element<'a, Message> {
    let header = text(state.title.clone()).size(24).color(Color::WHITE);

    let project_label = text(state.subtitle.clone())
        .size(14)
        .color(Color::from_rgb(0.6, 0.6, 0.7));

    let counts_row = row![
        stat_card(
            &t(locale, "dashboard.posts"),
            state.stats.total_posts.to_string(),
            {
                let mut details = vec![
                    format!(
                        "{} {}",
                        state.stats.published_count,
                        t(locale, "dashboard.published")
                    ),
                    format!(
                        "{} {}",
                        state.stats.draft_count,
                        t(locale, "dashboard.drafts")
                    ),
                ];
                if state.stats.archived_count > 0 {
                    details.push(format!(
                        "{} {}",
                        state.stats.archived_count,
                        t(locale, "dashboard.archived")
                    ));
                }
                details
            },
        ),
        stat_card(
            &t(locale, "dashboard.media"),
            state.stats.media_count.to_string(),
            vec![
                format!(
                    "{} {}",
                    state.stats.image_count,
                    t(locale, "dashboard.images")
                ),
                state.stats.total_media_size.clone(),
            ],
        ),
        stat_card(
            &t(locale, "dashboard.tags"),
            state.stats.tag_count.to_string(),
            vec![format!(
                "{} {}",
                state.stats.category_count,
                t(locale, "dashboard.categories")
            )],
        ),
    ]
    .spacing(16);

    let mut content =
        column![header, project_label, Space::new().height(16), counts_row].spacing(8);

    if !state.timeline.is_empty() {
        content = content
            .push(Space::new().height(20))
            .push(inputs::section_header(&t(locale, "dashboard.timeline")))
            .push(timeline_chart(&state.timeline, locale));
    }
    if !state.tag_cloud.is_empty() {
        content = content
            .push(Space::new().height(20))
            .push(inputs::section_header(&t(locale, "dashboard.tags")))
            .push(tag_cloud(&state.tag_cloud, locale));
    }
    if !state.category_cloud.is_empty() {
        content = content
            .push(Space::new().height(20))
            .push(inputs::section_header(&t(locale, "dashboard.categories")))
            .push(category_cloud(&state.category_cloud, locale));
    }
    if !state.recent_posts.is_empty() {
        content = content
            .push(Space::new().height(20))
            .push(inputs::section_header(&t(locale, "dashboard.recentPosts")))
            .push(recent_posts(&state.recent_posts, locale));
    }

    scrollable(container(content.padding(24).width(Length::Fill)))
        .direction(scrollable::Direction::Vertical(inputs::compact_scrollbar()))
        .style(inputs::scrollable_style)
        .width(Length::Fill)
        .height(Length::Fill)
        .into()
}

fn stat_card<'a>(label: &str, value: String, details: Vec<String>) -> Element<'a, Message> {
    container(
        column(
            std::iter::once(text(value).size(28).color(Color::WHITE).into())
                .chain(std::iter::once(
                    text(label.to_string())
                        .size(12)
                        .color(Color::from_rgb(0.55, 0.58, 0.65))
                        .into(),
                ))
                .chain(details.into_iter().map(|detail| {
                    text(detail)
                        .size(12)
                        .color(Color::from_rgb(0.72, 0.74, 0.80))
                        .into()
                }))
                .collect::<Vec<Element<'a, Message>>>(),
        )
        .spacing(4)
        .align_x(Alignment::Center),
    )
    .padding(16)
    .width(Length::FillPortion(1))
    .style(|_: &Theme| container::Style {
        background: Some(Background::Color(inputs::SURFACE_BG)),
        border: iced::Border {
            radius: 8.0.into(),
            ..iced::Border::default()
        },
        ..container::Style::default()
    })
    .into()
}

fn timeline_chart<'a>(
    months: &'a [DashboardTimelineMonth],
    _locale: UiLocale,
) -> Element<'a, Message> {
    let max_count = months
        .iter()
        .map(|month| month.count)
        .max()
        .unwrap_or(1)
        .max(1);
    row(months
        .iter()
        .map(|month| {
            let height = if month.count == 0 {
                8.0
            } else {
                24.0 + (month.count as f32 / max_count as f32) * 96.0
            };
            container(
                column![
                    text(month.count.to_string()).size(12).color(Color::WHITE),
                    container(Space::new().height(height))
                        .width(Length::Fill)
                        .style(|_: &Theme| container::Style {
                            background: Some(Background::Color(Color::from_rgb(0.25, 0.48, 0.80))),
                            border: iced::Border {
                                radius: 6.0.into(),
                                ..iced::Border::default()
                            },
                            ..container::Style::default()
                        }),
                    text(format!("{} {}", month.label, month.year))
                        .size(11)
                        .color(Color::from_rgb(0.7, 0.72, 0.78)),
                ]
                .spacing(6)
                .align_x(Alignment::Center),
            )
            .width(Length::FillPortion(1))
            .into()
        })
        .collect::<Vec<_>>())
    .spacing(10)
    .align_y(Alignment::End)
    .into()
}

fn tag_cloud<'a>(tags: &'a [DashboardTag], locale: UiLocale) -> Element<'a, Message> {
    let words = tags
        .iter()
        .map(|tag| {
            let bg = parse_color(tag.color.as_deref()).unwrap_or(Color::from_rgb(0.18, 0.21, 0.28));
            let fg = contrast_color(bg);
            tooltip(
                container(text(tag.name.clone()).size(tag.font_size).color(fg))
                    .padding([6, 10])
                    .style(move |_: &Theme| container::Style {
                        background: Some(Background::Color(bg)),
                        border: iced::Border {
                            radius: 999.0.into(),
                            ..iced::Border::default()
                        },
                        ..container::Style::default()
                    }),
                text(post_count_label(locale, tag.count)).size(12),
                tooltip::Position::Top,
            )
            .into()
        })
        .collect::<Vec<_>>();
    row(words).spacing(8).wrap().into()
}

fn category_cloud<'a>(
    categories: &'a [DashboardCategory],
    locale: UiLocale,
) -> Element<'a, Message> {
    let badges = categories
        .iter()
        .map(|category| {
            tooltip(
                container(
                    row![
                        text(category.name.clone()).size(13).color(Color::WHITE),
                        text(category.count.to_string())
                            .size(12)
                            .color(Color::from_rgb(0.72, 0.74, 0.80)),
                    ]
                    .spacing(8),
                )
                .padding([6, 10])
                .style(|_: &Theme| container::Style {
                    background: Some(Background::Color(inputs::ELEVATED_BG)),
                    border: iced::Border {
                        radius: 999.0.into(),
                        ..iced::Border::default()
                    },
                    ..container::Style::default()
                }),
                text(post_count_label(locale, category.count)).size(12),
                tooltip::Position::Top,
            )
            .into()
        })
        .collect::<Vec<_>>();
    row(badges).spacing(8).wrap().into()
}

fn post_count_label(locale: UiLocale, count: usize) -> String {
    tw(
        locale,
        "dashboard.postCount",
        &[("count", &count.to_string())],
    )
}

fn recent_posts<'a>(posts: &'a [DashboardRecentPost], locale: UiLocale) -> Element<'a, Message> {
    column(
        posts
            .iter()
            .map(|post| {
                container(
                    row![
                        keyboard::button(
                            column![
                                text(post.title.clone()).size(14).color(Color::WHITE),
                                text(post.date.clone())
                                    .size(12)
                                    .color(Color::from_rgb(0.6, 0.62, 0.68)),
                            ]
                            .spacing(4),
                        )
                        .on_press(Message::OpenTab(Tab {
                            id: post.post_id.clone(),
                            tab_type: TabType::Post,
                            title: post.title.clone(),
                            is_transient: true,
                            is_dirty: false,
                        }))
                        .width(Length::Fill),
                        status_badge(&post.status),
                        keyboard::button(text(t(locale, "dashboard.pin")).size(12))
                            .on_press(Message::OpenTab(Tab {
                                id: post.post_id.clone(),
                                tab_type: TabType::Post,
                                title: post.title.clone(),
                                is_transient: false,
                                is_dirty: false,
                            }))
                            .padding([6, 10]),
                    ]
                    .spacing(12)
                    .align_y(Alignment::Center),
                )
                .padding(12)
                .style(|_: &Theme| container::Style {
                    background: Some(Background::Color(inputs::ELEVATED_BG)),
                    border: iced::Border {
                        radius: 8.0.into(),
                        ..iced::Border::default()
                    },
                    ..container::Style::default()
                })
                .into()
            })
            .collect::<Vec<_>>(),
    )
    .spacing(8)
    .into()
}

fn status_badge<'a>(status: &str) -> Element<'a, Message> {
    let bg = if status.eq_ignore_ascii_case("published") {
        Color::from_rgb(0.16, 0.42, 0.24)
    } else {
        Color::from_rgb(0.45, 0.33, 0.14)
    };
    container(text(status.to_string()).size(11).color(Color::WHITE))
        .padding([4, 8])
        .style(move |_: &Theme| container::Style {
            background: Some(Background::Color(bg)),
            border: iced::Border {
                radius: 999.0.into(),
                ..iced::Border::default()
            },
            ..container::Style::default()
        })
        .into()
}

fn parse_color(value: Option<&str>) -> Option<Color> {
    let value = value?.trim_start_matches('#');
    if value.len() != 6 {
        return None;
    }
    let red = u8::from_str_radix(&value[0..2], 16).ok()?;
    let green = u8::from_str_radix(&value[2..4], 16).ok()?;
    let blue = u8::from_str_radix(&value[4..6], 16).ok()?;
    Some(Color::from_rgb8(red, green, blue))
}

fn contrast_color(background: Color) -> Color {
    let luma = 0.299 * background.r + 0.587 * background.g + 0.114 * background.b;
    if luma > 0.55 {
        Color::BLACK
    } else {
        Color::WHITE
    }
}
