use ratatui::{
    buffer::Buffer,
    layout::Rect,
    style::{Color, Modifier, Style},
};

use crate::model::Model;
use crate::ui::app::AppMode;
use crate::ui::cat_tree::{CatTreeEntry, build_cat_tree};
use crate::ui::panel::PanelContent;
use crate::view::{Axis, View};

fn axis_display(axis: Axis) -> (&'static str, Color) {
    match axis {
        Axis::Row => ("Row ↕", Color::Green),
        Axis::Column => ("Col ↔", Color::Blue),
        Axis::Page => ("Page ☰", Color::Magenta),
        Axis::None => ("None ∅", Color::DarkGray),
    }
}

pub struct CategoryContent<'a> {
    view: &'a View,
    tree: Vec<CatTreeEntry>,
}

impl<'a> CategoryContent<'a> {
    pub fn new(
        model: &'a Model,
        view: &'a View,
        expanded: &'a std::collections::HashSet<String>,
    ) -> Self {
        let tree = build_cat_tree(model, expanded);
        Self { view, tree }
    }
}

impl PanelContent for CategoryContent<'_> {
    fn is_active(&self, mode: &AppMode) -> bool {
        matches!(
            mode,
            AppMode::CategoryPanel | AppMode::ItemAdd { .. } | AppMode::CategoryAdd { .. }
        )
    }

    fn active_color(&self) -> Color {
        Color::Cyan
    }

    fn title(&self) -> &str {
        " Categories "
    }

    fn item_count(&self) -> usize {
        self.tree.len()
    }

    fn empty_message(&self) -> &str {
        "(no categories — use :add-cat <name>)"
    }

    fn render_item(&self, index: usize, is_selected: bool, inner: Rect, buf: &mut Buffer) {
        let y = inner.y + index as u16;
        let view = self.view;

        let base_style = if is_selected {
            Style::default()
                .fg(Color::Black)
                .bg(Color::Cyan)
                .add_modifier(Modifier::BOLD)
        } else {
            Style::default()
        };

        if is_selected {
            let fill = " ".repeat(inner.width as usize);
            buf.set_string(inner.x, y, &fill, base_style);
        }

        match &self.tree[index] {
            CatTreeEntry::Category {
                name,
                item_count,
                expanded,
            } => {
                let indicator = if *expanded { "▼" } else { "▶" };
                let (axis_str, axis_color) = axis_display(view.axis_of(name));
                let name_part = format!("{indicator} {name} ({item_count})");
                let axis_part = format!(" [{axis_str}]");

                buf.set_string(inner.x, y, &name_part, base_style);
                if name_part.len() + axis_part.len() < inner.width as usize {
                    buf.set_string(
                        inner.x + name_part.len() as u16,
                        y,
                        &axis_part,
                        if is_selected {
                            base_style
                        } else {
                            Style::default().fg(axis_color)
                        },
                    );
                }
            }
            CatTreeEntry::Item { item_name, .. } => {
                let label = format!("  · {item_name}");
                buf.set_string(inner.x, y, &label, base_style);
            }
        }
    }
}
