use crate::error::Result;
use crate::session::SessionMetadata;
use colored::Colorize;
use std::io::{self, Write};

const SECONDS_PER_MINUTE: u64 = 60;
const SECONDS_PER_HOUR: u64 = 60 * SECONDS_PER_MINUTE;
const SECONDS_PER_DAY: u64 = 24 * SECONDS_PER_HOUR;
const SECONDS_PER_WEEK: u64 = 7 * SECONDS_PER_DAY;

pub fn select_session(sessions: Vec<SessionMetadata>) -> Result<Option<String>> {
    if sessions.is_empty() {
        println!("{}", "No saved sessions found.".yellow());
        return Ok(None);
    }

    println!("\n{}", "Select a session to resume:".bright_cyan().bold());
    println!();

    for (i, session) in sessions.iter().enumerate() {
        let date = format_timestamp(session.updated_at);
        let msg_count = format!("{} messages", session.message_count);

        println!(
            "  {} {} {}",
            format!("[{}]", i + 1).bright_green().bold(),
            session.preview.bright_white(),
            format!("({} • {})", date, msg_count).dimmed()
        );
    }

    println!();
    print!("{} ", "Enter number (or 'q' to cancel):".dimmed());
    io::stdout().flush()?;

    let mut input = String::new();
    io::stdin().read_line(&mut input)?;
    let input = input.trim();

    if input.is_empty() || input == "q" || input == "quit" {
        return Ok(None);
    }

    match input.parse::<usize>() {
        Ok(num) if num > 0 && num <= sessions.len() => Ok(Some(sessions[num - 1].id.clone())),
        _ => {
            println!("{}", "Invalid selection".red());
            Ok(None)
        }
    }
}

fn format_timestamp(timestamp: u64) -> String {
    use std::time::{Duration, SystemTime, UNIX_EPOCH};

    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap_or(Duration::ZERO)
        .as_secs();
    let diff = now.saturating_sub(timestamp);

    if diff < SECONDS_PER_MINUTE {
        "just now".to_string()
    } else if diff < SECONDS_PER_HOUR {
        let mins = diff / SECONDS_PER_MINUTE;
        format!("{} min{} ago", mins, if mins == 1 { "" } else { "s" })
    } else if diff < SECONDS_PER_DAY {
        let hours = diff / SECONDS_PER_HOUR;
        format!("{} hour{} ago", hours, if hours == 1 { "" } else { "s" })
    } else if diff < SECONDS_PER_WEEK {
        let days = diff / SECONDS_PER_DAY;
        format!("{} day{} ago", days, if days == 1 { "" } else { "s" })
    } else {
        use chrono::{DateTime, Utc};
        let dt = DateTime::<Utc>::from(UNIX_EPOCH + Duration::from_secs(timestamp));
        dt.format("%Y-%m-%d").to_string()
    }
}
