use std::mem;

use ratatui::{
    crossterm::event::KeyEvent,
    macros::{constraint, constraints},
    prelude::*,
    text::Text,
    widgets::{Block, BorderType, Padding, Paragraph, Widget as _, Wrap},
};
use ratzgo::{
    core::{Element, OnKey, OnKeyBuilder, Widget},
    widget::Borders,
};

#[derive(Debug)]
pub struct Modal<'a, Message> {
    title: Line<'a>,
    text: Text<'a>,
    area: Rect,
    on_key: OnKey<'a, Message>,
}

impl<'a, Message> Modal<'a, Message> {
    pub fn new(title: impl Into<Line<'a>>, text: impl Into<Text<'a>>) -> Self {
        Self {
            title: title.into().centered(),
            text: text.into(),
            area: Default::default(),
            on_key: Default::default(),
        }
    }
}

impl<'a, Message> Widget<Message> for Modal<'a, Message>
where
    Message: std::fmt::Debug,
{
    fn activity(&self) -> bool {
        true
    }

    fn area(&self) -> Rect {
        self.area
    }

    fn set_area(&mut self, area: Rect) {
        self.area = area;
    }

    fn handle_key(&mut self, key: &KeyEvent) -> Option<Message> {
        self.on_key.key(key)
    }

    fn adapt(&mut self, buf: &mut Buffer) {
        let outer = Block::bordered()
            .border_type(BorderType::Rounded)
            .title(mem::take(&mut self.title).centered());

        let [area_content, area_bottom] =
            Layout::vertical(constraints![==100%, ==1]).areas(outer.inner(self.area));
        let [area_bottom_left, area_bottom_right] =
            Layout::horizontal(constraints![*=1, *=1]).areas(area_bottom);

        Paragraph::new(mem::take(&mut self.text))
            .wrap(Wrap { trim: false })
            .block(
                Block::default()
                    .borders(Borders::BOTTOM)
                    .padding(Padding::horizontal(1)),
            )
            .render(area_content, buf);

        Line::from("[Y]es").centered().render(area_bottom_left, buf);
        Line::from("(N)o").centered().render(area_bottom_right, buf);

        outer.render(self.area, buf);
    }
}

impl<'a, Message> From<Modal<'a, Message>> for Element<'a, Message>
where
    Message: std::fmt::Debug + 'static,
{
    fn from(widget: Modal<'a, Message>) -> Self {
        Element::new(widget)
    }
}

impl<'a, Message> OnKeyBuilder<'a, Message> for Modal<'a, Message> {
    fn on_key_mut(&mut self) -> &mut OnKey<'a, Message> {
        &mut self.on_key
    }
}

pub fn modal_area(area: Rect) -> Rect {
    area.centered(constraint!(==40%), constraint!(==40%))
}