use crate::database::Database;
use crate::ui::movie::library::LibraryItem;
use crate::ui::show::season_detail::EpisodeItem;

/// Bookkeeping for the currently playing media: what is playing (a movie by
/// id, or an episode by file path) and how to persist progress when playback
/// stops.
pub(crate) struct PlaybackSession {
    pub(crate) playing_movie_id: Option<i64>,
    pub(crate) last_played_episode_file: Option<String>,
    pub(crate) play_next: bool,
}

impl PlaybackSession {
    pub(crate) fn new() -> Self {
        Self {
            playing_movie_id: None,
            last_played_episode_file: None,
            play_next: true,
        }
    }

    /// The episode following the last played one within the loaded season.
    pub(crate) fn next_episode_file(&self, episodes: &[EpisodeItem]) -> Option<String> {
        let last = self.last_played_episode_file.as_ref()?;
        let idx = episodes.iter().position(|e| &e.file == last)?;
        episodes.get(idx + 1).map(|e| e.file.clone())
    }

    /// Save playback position or mark as watched, depending on how much was watched.
    pub(crate) fn check_and_mark_watched(
        &self,
        db: &mut Database,
        movies: &mut [LibraryItem],
        episodes: &mut [EpisodeItem],
        current_time: f64,
        total_duration: f64,
    ) {
        let watched = total_duration > 0.0 && current_time / total_duration >= 0.80;
        let save_pos = !watched && current_time > 5.0;

        if let Some(movie_id) = self.playing_movie_id {
            let Some(item) = movies.iter_mut().find(|m| m.id == movie_id) else {
                return;
            };
            if watched {
                if !item.watched {
                    if let Err(e) = db.set_movie_watched(true, item.id) {
                        log::error!("failed to auto-mark movie watched: {e}");
                    } else {
                        log::info!("auto-marked movie '{}' as watched", item.title);
                        item.watched = true;
                    }
                }
                if item.playback_position.is_some() {
                    if let Err(e) = db.clear_movie_playback(item.id) {
                        log::error!("failed to clear movie playback position: {e}");
                    } else {
                        item.playback_position = None;
                    }
                }
            } else if save_pos {
                if let Err(e) = db.update_movie_playback(current_time, item.id) {
                    log::error!("failed to save movie playback position: {e}");
                } else {
                    item.playback_position = Some(current_time);
                }
            }
        } else if let Some(file) = self.last_played_episode_file.as_deref() {
            let Some(ep) = episodes.iter_mut().find(|e| e.file == file) else {
                return;
            };
            if watched {
                if !ep.watched {
                    if let Err(e) = db.set_episode_watched(true, ep.id) {
                        log::error!("failed to auto-mark episode watched: {e}");
                    } else {
                        log::info!("auto-marked episode as watched");
                        ep.watched = true;
                    }
                }
                if ep.playback_position.is_some() {
                    if let Err(e) = db.clear_episode_playback(ep.id) {
                        log::error!("failed to clear episode playback position: {e}");
                    } else {
                        ep.playback_position = None;
                    }
                }
                if let Ok(Some(next)) = db.find_next_queueable_episode(ep.id)
                    && let Err(e) = db.update_episode_playback(0.0, next.id)
                {
                    log::error!("failed to queue next episode into continue watching: {e}");
                }
            } else if save_pos {
                if let Err(e) = db.update_episode_playback(current_time, ep.id) {
                    log::error!("failed to save episode playback position: {e}");
                } else {
                    ep.playback_position = Some(current_time);
                }
            }
        }
    }
}
