use chrono::Datelike;
use gtk::prelude::*;
use std::cell::Cell;
use std::rc::Rc;

const MONTH_NAMES: [&str; 12] = [
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
];

pub struct MonthNav {
    pub container: gtk::Box,
    pub year: Rc<Cell<i32>>,
    pub month: Rc<Cell<u32>>,
    label: gtk::Label,
}

impl MonthNav {
    pub fn new(on_change: impl Fn(i32, u32) + 'static) -> Self {
        let today = chrono::Local::now().date_naive();
        let year = Rc::new(Cell::new(today.year()));
        let month = Rc::new(Cell::new(today.month()));

        let container = gtk::Box::new(gtk::Orientation::Horizontal, 12);
        container.set_halign(gtk::Align::Center);
        container.set_margin_top(12);
        container.set_margin_bottom(12);

        let prev_btn = gtk::Button::from_icon_name("go-previous-symbolic");
        prev_btn.add_css_class("flat");
        prev_btn.add_css_class("circular");
        prev_btn.set_tooltip_text(Some("Previous month"));

        // Month label as a button that opens a picker popover
        let label = gtk::Label::new(None);
        label.add_css_class("month-nav-label");
        label.set_width_chars(18);

        let label_btn = gtk::Button::new();
        label_btn.set_child(Some(&label));
        label_btn.add_css_class("flat");
        label_btn.set_tooltip_text(Some("Pick a month"));

        let next_btn = gtk::Button::from_icon_name("go-next-symbolic");
        next_btn.add_css_class("flat");
        next_btn.add_css_class("circular");
        next_btn.set_tooltip_text(Some("Next month"));

        container.append(&prev_btn);
        container.append(&label_btn);
        container.append(&next_btn);

        let on_change = Rc::new(on_change);

        Self::update_label(&label, year.get(), month.get());

        // Month picker popover
        let popover = gtk::Popover::new();
        popover.set_parent(&label_btn);

        let picker_box = gtk::Box::new(gtk::Orientation::Vertical, 8);
        picker_box.set_margin_start(12);
        picker_box.set_margin_end(12);
        picker_box.set_margin_top(12);
        picker_box.set_margin_bottom(12);

        // Year row: prev year | year label | next year
        let year_row = gtk::Box::new(gtk::Orientation::Horizontal, 8);
        year_row.set_halign(gtk::Align::Center);

        let picker_year = Rc::new(Cell::new(year.get()));

        let year_label = gtk::Label::new(Some(&year.get().to_string()));
        year_label.add_css_class("heading");
        year_label.set_width_chars(6);

        let py_btn = gtk::Button::from_icon_name("go-previous-symbolic");
        py_btn.add_css_class("flat");
        py_btn.add_css_class("circular");
        let ny_btn = gtk::Button::from_icon_name("go-next-symbolic");
        ny_btn.add_css_class("flat");
        ny_btn.add_css_class("circular");

        year_row.append(&py_btn);
        year_row.append(&year_label);
        year_row.append(&ny_btn);
        picker_box.append(&year_row);

        {
            let py = picker_year.clone();
            let yl = year_label.clone();
            py_btn.connect_clicked(move |_| {
                py.set(py.get() - 1);
                yl.set_label(&py.get().to_string());
            });
        }
        {
            let py = picker_year.clone();
            let yl = year_label.clone();
            ny_btn.connect_clicked(move |_| {
                py.set(py.get() + 1);
                yl.set_label(&py.get().to_string());
            });
        }

        // 4x3 grid of month buttons
        let month_grid = gtk::Grid::new();
        month_grid.set_row_spacing(4);
        month_grid.set_column_spacing(4);

        for i in 0..12u32 {
            let btn = gtk::Button::with_label(MONTH_NAMES[i as usize]);
            btn.add_css_class("flat");
            btn.set_hexpand(true);

            let y = year.clone();
            let m = month.clone();
            let py = picker_year.clone();
            let lbl = label.clone();
            let cb = on_change.clone();
            let pop = popover.clone();
            btn.connect_clicked(move |_| {
                let new_month = i + 1;
                let new_year = py.get();
                y.set(new_year);
                m.set(new_month);
                Self::update_label(&lbl, new_year, new_month);
                cb(new_year, new_month);
                pop.popdown();
            });

            month_grid.attach(&btn, (i % 4) as i32, (i / 4) as i32, 1, 1);
        }

        picker_box.append(&month_grid);

        // "Today" button to quickly jump to current month
        let today_btn = gtk::Button::with_label("Today");
        today_btn.add_css_class("flat");
        {
            let y = year.clone();
            let m = month.clone();
            let lbl = label.clone();
            let cb = on_change.clone();
            let pop = popover.clone();
            today_btn.connect_clicked(move |_| {
                let now = chrono::Local::now().date_naive();
                y.set(now.year());
                m.set(now.month());
                Self::update_label(&lbl, now.year(), now.month());
                cb(now.year(), now.month());
                pop.popdown();
            });
        }
        picker_box.append(&today_btn);

        popover.set_child(Some(&picker_box));

        // Sync picker year when popover opens
        {
            let py = picker_year.clone();
            let y = year.clone();
            let yl = year_label.clone();
            popover.connect_show(move |_| {
                py.set(y.get());
                yl.set_label(&y.get().to_string());
            });
        }

        label_btn.connect_clicked(move |_| {
            popover.popup();
        });

        // Prev/Next buttons
        {
            let y = year.clone();
            let m = month.clone();
            let lbl = label.clone();
            let cb = on_change.clone();
            prev_btn.connect_clicked(move |_| {
                let mut yr = y.get();
                let mut mo = m.get();
                if mo == 1 {
                    mo = 12;
                    yr -= 1;
                } else {
                    mo -= 1;
                }
                y.set(yr);
                m.set(mo);
                Self::update_label(&lbl, yr, mo);
                cb(yr, mo);
            });
        }

        {
            let y = year.clone();
            let m = month.clone();
            let lbl = label.clone();
            let cb = on_change;
            next_btn.connect_clicked(move |_| {
                let mut yr = y.get();
                let mut mo = m.get();
                if mo == 12 {
                    mo = 1;
                    yr += 1;
                } else {
                    mo += 1;
                }
                y.set(yr);
                m.set(mo);
                Self::update_label(&lbl, yr, mo);
                cb(yr, mo);
            });
        }

        MonthNav { container, year, month, label }
    }

    pub fn set_month(&self, year: i32, month: u32) {
        self.year.set(year);
        self.month.set(month);
        Self::update_label(&self.label, year, month);
    }

    fn update_label(label: &gtk::Label, year: i32, month: u32) {
        let date = chrono::NaiveDate::from_ymd_opt(year, month, 1).unwrap();
        let month_name = date.format("%B %Y").to_string();
        label.set_label(&month_name);
    }
}
