use itertools::Itertools;
use ratatui::{
    buffer::Buffer,
    layout::{Alignment, Constraint, Layout, Margin, Rect},
    style::{Style, Stylize},
    text::Line,
    widgets::{
        Block, Clear, Padding, Paragraph, Row, Scrollbar, ScrollbarOrientation, ScrollbarState,
        StatefulWidget, Table, TableState, Widget, Wrap,
    },
};

use crate::{RgbSwatch, THEME};

#[derive(Debug, Default, Clone, Copy)]
struct Ingredient {
    quantity: &'static str,
    name: &'static str,
}

impl Ingredient {
    #[allow(clippy::cast_possible_truncation)]
    fn height(&self) -> u16 {
        self.name.lines().count() as u16
    }
}

impl<'a> From<Ingredient> for Row<'a> {
    fn from(i: Ingredient) -> Self {
        Row::new(vec![i.quantity, i.name]).height(i.height())
    }
}

// https://www.realsimple.com/food-recipes/browse-all-recipes/ratatouille
const RECIPE: &[(&str, &str)] = &[
    (
        "Step 1: ",
        "Over medium-low heat, add the oil to a large skillet with the onion, garlic, and bay \
        leaf, stirring occasionally, until the onion has softened.",
    ),
    (
        "Step 2: ",
        "Add the eggplant and cook, stirring occasionally, for 8 minutes or until the eggplant \
        has softened. Stir in the zucchini, red bell pepper, tomatoes, and salt, and cook over \
        medium heat, stirring occasionally, for 5 to 7 minutes or until the vegetables are \
        tender. Stir in the basil and few grinds of pepper to taste.",
    ),
];

const INGREDIENTS: &[Ingredient] = &[
    Ingredient {
        quantity: "4 tbsp",
        name: "olive oil",
    },
    Ingredient {
        quantity: "1",
        name: "onion thinly sliced",
    },
    Ingredient {
        quantity: "4",
        name: "cloves garlic\npeeled and sliced",
    },
    Ingredient {
        quantity: "1",
        name: "small bay leaf",
    },
    Ingredient {
        quantity: "1",
        name: "small eggplant cut\ninto 1/2 inch cubes",
    },
    Ingredient {
        quantity: "1",
        name: "small zucchini halved\nlengthwise and cut\ninto thin slices",
    },
    Ingredient {
        quantity: "1",
        name: "red bell pepper cut\ninto slivers",
    },
    Ingredient {
        quantity: "4",
        name: "plum tomatoes\ncoarsely chopped",
    },
    Ingredient {
        quantity: "1 tsp",
        name: "kosher salt",
    },
    Ingredient {
        quantity: "1/4 cup",
        name: "shredded fresh basil\nleaves",
    },
    Ingredient {
        quantity: "",
        name: "freshly ground black\npepper",
    },
];

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct RecipeTab {
    row_index: usize,
}

impl RecipeTab {
    /// Select the previous item in the ingredients list (with wrap around)
    pub fn prev(&mut self) {
        self.row_index = self.row_index.saturating_add(INGREDIENTS.len() - 1) % INGREDIENTS.len();
    }

    /// Select the next item in the ingredients list (with wrap around)
    pub fn next(&mut self) {
        self.row_index = self.row_index.saturating_add(1) % INGREDIENTS.len();
    }
}

impl Widget for RecipeTab {
    fn render(self, area: Rect, buf: &mut Buffer) {
        RgbSwatch.render(area, buf);
        let area = area.inner(Margin {
            vertical: 1,
            horizontal: 2,
        });
        Clear.render(area, buf);
        Block::new()
            .title("Ratatouille Recipe".bold().white())
            .title_alignment(Alignment::Center)
            .style(THEME.content)
            .padding(Padding::new(1, 1, 2, 1))
            .render(area, buf);

        let scrollbar_area = Rect {
            y: area.y + 2,
            height: area.height - 3,
            ..area
        };
        render_scrollbar(self.row_index, scrollbar_area, buf);

        let area = area.inner(Margin {
            horizontal: 2,
            vertical: 1,
        });
        let [recipe, ingredients] =
            Layout::horizontal([Constraint::Length(44), Constraint::Min(0)]).areas(area);

        render_recipe(recipe, buf);
        render_ingredients(self.row_index, ingredients, buf);
    }
}

fn render_recipe(area: Rect, buf: &mut Buffer) {
    let lines = RECIPE
        .iter()
        .map(|(step, text)| Line::from(vec![step.white().bold(), text.gray()]))
        .collect_vec();
    Paragraph::new(lines)
        .wrap(Wrap { trim: true })
        .block(Block::new().padding(Padding::new(0, 1, 0, 0)))
        .render(area, buf);
}

fn render_ingredients(selected_row: usize, area: Rect, buf: &mut Buffer) {
    let mut state = TableState::default().with_selected(Some(selected_row));
    let rows = INGREDIENTS.iter().copied();
    let theme = THEME.recipe;
    StatefulWidget::render(
        Table::new(rows, [Constraint::Length(7), Constraint::Length(30)])
            .block(Block::new().style(theme.ingredients))
            .header(Row::new(vec!["Qty", "Ingredient"]).style(theme.ingredients_header))
            .highlight_style(Style::new().light_yellow()),
        area,
        buf,
        &mut state,
    );
}

fn render_scrollbar(position: usize, area: Rect, buf: &mut Buffer) {
    let mut state = ScrollbarState::default()
        .content_length(INGREDIENTS.len())
        .viewport_content_length(6)
        .position(position);
    Scrollbar::new(ScrollbarOrientation::VerticalRight)
        .begin_symbol(None)
        .end_symbol(None)
        .track_symbol(None)
        .thumb_symbol("▐")
        .render(area, buf, &mut state);
}
