use anyhow::{anyhow, Result};
use rand::seq::SliceRandom;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct Edition {
    pub edition: u8,
    pub year: u16,
    pub strategies: Vec<String>,
}

const EDITION_1: &str = include_str!("../data/edition_1.yaml");
const EDITION_2: &str = include_str!("../data/edition_2.yaml");
const EDITION_3: &str = include_str!("../data/edition_3.yaml");
const EDITION_4: &str = include_str!("../data/edition_4.yaml");

pub fn load_edition(edition: u8) -> Result<Edition> {
    let yaml = match edition {
        1 => EDITION_1,
        2 => EDITION_2,
        3 => EDITION_3,
        4 => EDITION_4,
        _ => return Err(anyhow!("Invalid edition: {}. Must be 1-4.", edition)),
    };

    let data: Edition = serde_yaml::from_str(yaml)?;
    Ok(data)
}

pub fn random_strategy(edition: &Edition) -> &str {
    let mut rng = rand::thread_rng();
    edition
        .strategies
        .choose(&mut rng)
        .map(|s| s.as_str())
        .unwrap_or("Trust in the you of now")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_load_edition_1() {
        let edition = load_edition(1).unwrap();
        assert_eq!(edition.edition, 1);
        assert_eq!(edition.year, 1975);
        assert!(!edition.strategies.is_empty());
    }

    #[test]
    fn test_load_edition_2() {
        let edition = load_edition(2).unwrap();
        assert_eq!(edition.edition, 2);
        assert_eq!(edition.year, 1978);
        assert!(!edition.strategies.is_empty());
    }

    #[test]
    fn test_load_edition_3() {
        let edition = load_edition(3).unwrap();
        assert_eq!(edition.edition, 3);
        assert_eq!(edition.year, 1979);
        assert!(!edition.strategies.is_empty());
    }

    #[test]
    fn test_load_edition_4() {
        let edition = load_edition(4).unwrap();
        assert_eq!(edition.edition, 4);
        assert_eq!(edition.year, 1996);
        assert!(!edition.strategies.is_empty());
    }

    #[test]
    fn test_load_invalid_edition() {
        assert!(load_edition(0).is_err());
        assert!(load_edition(5).is_err());
    }

    #[test]
    fn test_random_strategy() {
        let edition = load_edition(4).unwrap();
        let strategy = random_strategy(&edition);
        assert!(!strategy.is_empty());
        assert!(edition.strategies.contains(&strategy.to_string()));
    }
}
