use super::styles::{self, GRAY_40, GRAY_60, GRAY_70, GRAY_80};
use crate::ui::Message;
use iced::Element;

pub(crate) const RESULT_POSTER_WIDTH: f32 = 80.0;
pub(crate) const RESULT_POSTER_HEIGHT: f32 = 120.0;

pub(crate) trait TmdbResultDisplay {
    fn title(&self) -> &str;
    fn year_str(&self) -> &str;
    fn poster_image(&self) -> Option<&[u8]>;
}

pub(crate) fn tmdb_search_section<'a, R: TmdbResultDisplay>(
    search_expanded: bool,
    searching: bool,
    matching: bool,
    matching_text: &str,
    search_query: &'a str,
    search_placeholder: &str,
    search_results: &'a [R],
    error: &'a Option<String>,
    on_toggle: Message,
    on_query_changed: fn(String) -> Message,
    on_submit: Message,
    on_select: fn(usize) -> Message,
) -> Element<'a, Message> {
    let mut section = iced::widget::column![].spacing(styles::SPACING_MEDIUM);

    if !search_expanded {
        let toggle_btn = iced::widget::button(
            iced::widget::text("Change TMDB match")
                .size(14)
                .color(GRAY_70),
        )
        .on_press(on_toggle)
        .padding(iced::Padding::from([6.0, 16.0]))
        .style(styles::tmdb_toggle_button_style);

        return section.push(toggle_btn).into();
    }

    let label = iced::widget::text("TMDB Search").size(18).color(GRAY_80);
    section = section.push(label);

    if matching {
        section = section.push(
            iced::widget::text(matching_text.to_string())
                .size(14)
                .color(GRAY_60),
        );
        return section.into();
    }

    let search_input = iced::widget::text_input(search_placeholder, search_query)
        .on_input(on_query_changed)
        .on_submit(on_submit.clone())
        .size(14)
        .padding(8)
        .width(400);

    let mut search_btn = iced::widget::button(
        iced::widget::text("Search")
            .size(14)
            .color(iced::Color::WHITE),
    )
    .padding(iced::Padding::from([8.0, 16.0]))
    .style(styles::blue_button_style);

    if !searching && !search_query.trim().is_empty() {
        search_btn = search_btn.on_press(on_submit);
    }

    let search_row = iced::widget::row![search_input, search_btn].spacing(styles::SPACING_DEFAULT);
    section = section.push(search_row);

    if searching {
        section = section.push(iced::widget::text("Searching...").size(14).color(GRAY_60));
    }

    if let Some(error) = error {
        section = section.push(
            iced::widget::text(error)
                .size(14)
                .color(iced::Color::from_rgb(0.9, 0.3, 0.3)),
        );
    }

    for (idx, result) in search_results.iter().enumerate() {
        section = section.push(result_row(idx, result, on_select));
    }

    section.into()
}

fn result_row<'a>(
    idx: usize,
    result: &'a dyn TmdbResultDisplay,
    on_select: fn(usize) -> Message,
) -> Element<'a, Message> {
    let poster: Element<_> = if let Some(bytes) = result.poster_image() {
        iced::widget::image(iced::widget::image::Handle::from_bytes(bytes.to_vec()))
            .width(RESULT_POSTER_WIDTH)
            .height(RESULT_POSTER_HEIGHT)
            .into()
    } else {
        iced::widget::container(iced::widget::text("?").size(20).color(GRAY_40))
            .width(RESULT_POSTER_WIDTH)
            .height(RESULT_POSTER_HEIGHT)
            .center_x(RESULT_POSTER_WIDTH)
            .center_y(RESULT_POSTER_HEIGHT)
            .style(styles::placeholder_style)
            .into()
    };

    let info = iced::widget::column![
        iced::widget::text(result.title())
            .size(16)
            .color(iced::Color::WHITE),
        iced::widget::text(result.year_str())
            .size(13)
            .color(GRAY_60),
    ]
    .spacing(styles::SPACING_TIGHT);

    let select_btn = iced::widget::button(
        iced::widget::text("Select")
            .size(13)
            .color(iced::Color::WHITE),
    )
    .on_press(on_select(idx))
    .padding(iced::Padding::from([6.0, 14.0]))
    .style(styles::green_button_style);

    let row = iced::widget::row![
        poster,
        info.width(iced::Length::Fill),
        iced::widget::container(select_btn).center_y(RESULT_POSTER_HEIGHT),
    ]
    .spacing(styles::SPACING_MEDIUM)
    .align_y(iced::Alignment::Start);

    iced::widget::container(row)
        .padding(8)
        .style(styles::result_row_style)
        .into()
}
