use crate::ui::Message as RootMessage;
use crate::ui::movie::library::LibraryItem;
use crate::ui::shared::cover::{
    COVER_HEIGHT, COVER_WIDTH, cover_placeholder, cover_with_watched_badge, media_card,
};
use crate::ui::shared::styles::{self, GRAY_50, GRAY_70, GRAY_80, GRAY_85};
use chrono::{DateTime, Utc};
use iced::{Element, Task};
use std::path::PathBuf;

const BACKDROP_WIDTH: f32 = 320.0;
const BACKDROP_HEIGHT: f32 = 180.0;
const CARD_SPACING: f32 = 12.0;

#[derive(Debug, Clone)]
pub(crate) enum Message {
    ContinueWatchingPrev,
    ContinueWatchingNext,
    RecentMoviesPrev,
    RecentMoviesNext,
    RecentSeasonsPrev,
    RecentSeasonsNext,
}

pub(crate) struct State {
    pub(crate) continue_watching: Vec<ContinueWatchingItem>,
    pub(crate) recent_movies: Vec<LibraryItem>,
    pub(crate) recent_seasons: Vec<RecentSeasonItem>,
    pub(crate) cw_offset: usize,
    pub(crate) movies_offset: usize,
    pub(crate) seasons_offset: usize,
}

pub(crate) fn update(state: &mut State, msg: Message) -> Task<RootMessage> {
    match msg {
        Message::ContinueWatchingPrev => {
            state.cw_offset = state.cw_offset.saturating_sub(4);
        }
        Message::ContinueWatchingNext => {
            state.cw_offset =
                (state.cw_offset + 4).min(state.continue_watching.len().saturating_sub(1));
        }
        Message::RecentMoviesPrev => {
            state.movies_offset = state.movies_offset.saturating_sub(4);
        }
        Message::RecentMoviesNext => {
            state.movies_offset =
                (state.movies_offset + 4).min(state.recent_movies.len().saturating_sub(1));
        }
        Message::RecentSeasonsPrev => {
            state.seasons_offset = state.seasons_offset.saturating_sub(4);
        }
        Message::RecentSeasonsNext => {
            state.seasons_offset =
                (state.seasons_offset + 4).min(state.recent_seasons.len().saturating_sub(1));
        }
    }
    Task::none()
}

pub(crate) struct RecentSeasonItem {
    pub(crate) show_id: i64,
    pub(crate) show_title: String,
    pub(crate) season_number: i64,
    pub(crate) title: Option<String>,
    pub(crate) cover_path: Option<PathBuf>,
    pub(crate) watched: bool,
}

pub(crate) enum ContinueWatchingMediaType {
    Movie { id: i64 },
    Episode { show_id: i64, season_id: i64 },
}

pub(crate) struct ContinueWatchingItem {
    pub(crate) title: String,
    pub(crate) file: String,
    pub(crate) backdrop_path: Option<PathBuf>,
    pub(crate) playback_position: f64,
    pub(crate) duration: Option<f64>,
    pub(crate) last_playback: DateTime<Utc>,
    pub(crate) media_type: ContinueWatchingMediaType,
}

pub(crate) fn view(state: &State) -> Element<'_, RootMessage> {
    let mut content = iced::widget::column![]
        .spacing(styles::SPACING_LARGE)
        .padding(iced::Padding::new(styles::PADDING_STANDARD));

    if !state.continue_watching.is_empty() {
        content = content.push(continue_watching_section(
            &state.continue_watching,
            state.cw_offset,
        ));
    }

    if !state.recent_movies.is_empty() {
        content = content.push(movie_section(&state.recent_movies, state.movies_offset));
    }

    if !state.recent_seasons.is_empty() {
        content = content.push(season_section(&state.recent_seasons, state.seasons_offset));
    }

    if state.continue_watching.is_empty()
        && state.recent_movies.is_empty()
        && state.recent_seasons.is_empty()
    {
        content = content.push(
            iced::widget::text("No content yet. Use --scan or --scan-shows to add media.")
                .color(GRAY_50),
        );
    }

    iced::widget::scrollable(content)
        .width(iced::Length::Fill)
        .height(iced::Length::Fill)
        .into()
}

fn section_title_row(
    label: &str,
    start: usize,
    end: usize,
    total: usize,
    prev_msg: RootMessage,
    next_msg: RootMessage,
) -> Element<'static, RootMessage> {
    let title = iced::widget::text(label.to_string())
        .size(styles::TEXT_SIZE_SECTION)
        .color(GRAY_85);

    let row = iced::widget::row![
        title,
        iced::widget::Space::new().width(iced::Length::Fill),
        nav_button("<", if start > 0 { Some(prev_msg) } else { None }),
        nav_button(">", if end < total { Some(next_msg) } else { None }),
    ]
    .spacing(styles::SPACING_DEFAULT)
    .align_y(iced::Alignment::Center);

    row.into()
}

fn nav_button(label: &str, msg: Option<RootMessage>) -> Element<'static, RootMessage> {
    let enabled = msg.is_some();
    let mut btn = iced::widget::button(
        iced::widget::text(label.to_string())
            .size(styles::TEXT_SIZE_BODY)
            .color(if enabled { GRAY_85 } else { GRAY_50 }),
    )
    .padding(iced::Padding::from([2.0, 10.0]))
    .style(move |_theme, status| {
        let bg = if !enabled {
            styles::BG_CARD
        } else {
            match status {
                iced::widget::button::Status::Hovered => styles::BG_PLACEHOLDER,
                _ => styles::BG_CARD,
            }
        };
        iced::widget::button::Style {
            background: Some(iced::Background::Color(bg)),
            text_color: if enabled { GRAY_85 } else { GRAY_50 },
            border: iced::border::rounded(styles::RADIUS_STANDARD),
            ..Default::default()
        }
    });

    if let Some(m) = msg {
        btn = btn.on_press(m);
    }

    btn.into()
}

fn continue_watching_section(
    items: &[ContinueWatchingItem],
    offset: usize,
) -> Element<'_, RootMessage> {
    let bd_w = BACKDROP_WIDTH;
    let bd_h = BACKDROP_HEIGHT;
    let card_w = bd_w + 8.0;

    iced::widget::responsive(move |size| {
        let visible_count = ((size.width + CARD_SPACING) / (card_w + CARD_SPACING))
            .floor()
            .max(1.0) as usize;
        let start = offset.min(items.len().saturating_sub(visible_count));
        let end = (start + visible_count).min(items.len());

        let header = section_title_row(
            "Continue Watching",
            start,
            end,
            items.len(),
            RootMessage::Home(Message::ContinueWatchingPrev),
            RootMessage::Home(Message::ContinueWatchingNext),
        );

        let mut row = iced::widget::row![].spacing(CARD_SPACING);

        for (i, item) in items.iter().enumerate().take(end).skip(start) {
            let backdrop: Element<_> = if let Some(path) = &item.backdrop_path {
                iced::widget::image(iced::widget::image::Handle::from_path(path))
                    .width(bd_w)
                    .height(bd_h)
                    .content_fit(iced::ContentFit::Cover)
                    .into()
            } else {
                iced::widget::container(
                    iced::widget::text(&item.title)
                        .size(styles::TEXT_SIZE_SMALL)
                        .color(GRAY_70)
                        .wrapping(iced::widget::text::Wrapping::WordOrGlyph),
                )
                .width(bd_w)
                .height(bd_h)
                .style(|_| iced::widget::container::Style {
                    background: Some(iced::Background::Color(styles::BG_PLACEHOLDER)),
                    border: iced::border::rounded(styles::RADIUS_STANDARD),
                    ..Default::default()
                })
                .align_x(iced::alignment::Horizontal::Center)
                .align_y(iced::alignment::Vertical::Center)
                .into()
            };

            let image_with_bar: Element<_> = if let Some(dur) = item.duration.filter(|&d| d > 0.0) {
                let progress_bar: Element<_> =
                    iced::widget::progress_bar(0.0..=dur as f32, item.playback_position as f32)
                        .length(bd_w)
                        .girth(4.0)
                        .style(|_theme| iced::widget::progress_bar::Style {
                            background: styles::BG_PLACEHOLDER.into(),
                            bar: styles::ACCENT_RED.into(),
                            border: iced::Border::default(),
                        })
                        .into();
                iced::widget::stack![
                    backdrop,
                    iced::widget::container(progress_bar)
                        .width(bd_w)
                        .height(bd_h)
                        .align_bottom(bd_h),
                ]
                .into()
            } else {
                backdrop
            };

            let label = iced::widget::text(&item.title)
                .size(styles::CARD_LABEL_SIZE)
                .color(GRAY_80)
                .wrapping(iced::widget::text::Wrapping::WordOrGlyph);

            let card = media_card(
                image_with_bar,
                label.into(),
                iced::Length::Fixed(bd_w),
                RootMessage::ContinueWatchingClicked(i),
            );

            row = row.push(card);
        }

        iced::widget::column![header, row.width(iced::Length::Fill)]
            .spacing(styles::SPACING_DEFAULT)
            .width(iced::Length::Fill)
            .into()
    })
    .into()
}

fn movie_section(items: &[LibraryItem], offset: usize) -> Element<'_, RootMessage> {
    let cover_w = COVER_WIDTH;
    let cover_h = COVER_HEIGHT;
    let card_w = cover_w + 8.0;

    iced::widget::responsive(move |size| {
        let visible_count = ((size.width + CARD_SPACING) / (card_w + CARD_SPACING))
            .floor()
            .max(1.0) as usize;
        let start = offset.min(items.len().saturating_sub(visible_count));
        let end = (start + visible_count).min(items.len());

        let header = section_title_row(
            "Recently Added Movies",
            start,
            end,
            items.len(),
            RootMessage::Home(Message::RecentMoviesPrev),
            RootMessage::Home(Message::RecentMoviesNext),
        );

        let mut row = iced::widget::row![].spacing(CARD_SPACING);

        for item in &items[start..end] {
            let year_str = item
                .release_year
                .map(|y| format!("({})", y))
                .unwrap_or_default();

            let cover_content: Element<_> = if let Some(path) = &item.cover_path {
                iced::widget::image(iced::widget::image::Handle::from_path(path))
                    .width(cover_w)
                    .height(cover_h)
                    .into()
            } else {
                cover_placeholder(&item.title, &year_str, cover_w, cover_h)
            };

            let cover_content =
                cover_with_watched_badge(cover_content, item.watched, cover_w, cover_h);

            let label = iced::widget::text(format!("{} {}", item.title, year_str))
                .size(styles::CARD_LABEL_SIZE)
                .color(GRAY_80)
                .wrapping(iced::widget::text::Wrapping::WordOrGlyph);

            let card = media_card(
                cover_content,
                label.into(),
                iced::Length::Fixed(cover_w),
                RootMessage::MovieDetail(item.id),
            );

            row = row.push(card);
        }

        iced::widget::column![header, row.width(iced::Length::Fill)]
            .spacing(styles::SPACING_DEFAULT)
            .width(iced::Length::Fill)
            .into()
    })
    .into()
}

fn season_section(items: &[RecentSeasonItem], offset: usize) -> Element<'_, RootMessage> {
    let cover_w = COVER_WIDTH;
    let cover_h = COVER_HEIGHT;
    let card_w = cover_w + 8.0;

    iced::widget::responsive(move |size| {
        let visible_count = ((size.width + CARD_SPACING) / (card_w + CARD_SPACING))
            .floor()
            .max(1.0) as usize;
        let start = offset.min(items.len().saturating_sub(visible_count));
        let end = (start + visible_count).min(items.len());

        let header = section_title_row(
            "Recently Added Seasons",
            start,
            end,
            items.len(),
            RootMessage::Home(Message::RecentSeasonsPrev),
            RootMessage::Home(Message::RecentSeasonsNext),
        );

        let mut row = iced::widget::row![].spacing(CARD_SPACING);

        for item in &items[start..end] {
            let season_label = item
                .title
                .clone()
                .unwrap_or_else(|| format!("Season {}", item.season_number));

            let cover_content: Element<_> = if let Some(path) = &item.cover_path {
                iced::widget::image(iced::widget::image::Handle::from_path(path))
                    .width(cover_w)
                    .height(cover_h)
                    .into()
            } else {
                cover_placeholder(&item.show_title, &season_label, cover_w, cover_h)
            };

            let cover_content =
                cover_with_watched_badge(cover_content, item.watched, cover_w, cover_h);

            let label = iced::widget::text(format!("{} - {}", item.show_title, season_label))
                .size(styles::CARD_LABEL_SIZE)
                .color(GRAY_80)
                .wrapping(iced::widget::text::Wrapping::WordOrGlyph);

            let card = media_card(
                cover_content,
                label.into(),
                iced::Length::Fixed(cover_w),
                RootMessage::ShowDetail(item.show_id),
            );

            row = row.push(card);
        }

        iced::widget::column![header, row.width(iced::Length::Fill)]
            .spacing(styles::SPACING_DEFAULT)
            .width(iced::Length::Fill)
            .into()
    })
    .into()
}
