use rand::seq::SliceRandom;
use rand::thread_rng;
use std::collections::HashSet;

pub struct JokeEngine {
    told: HashSet<usize>,
    language: JokeLanguage,
}

enum JokeLanguage {
    Russian,
    English,
}

impl JokeEngine {
    pub fn new_ru() -> Self {
        Self { told: HashSet::new(), language: JokeLanguage::Russian }
    }

    pub fn new_en() -> Self {
        Self { told: HashSet::new(), language: JokeLanguage::English }
    }

    pub fn random(&mut self) -> Option<&'static str> {
        let pool = match self.language {
            JokeLanguage::Russian => &RUSSIAN_JOKES[..],
            JokeLanguage::English => &ENGLISH_JOKES[..],
        };

        let available: Vec<usize> = (0..pool.len())
            .filter(|i| !self.told.contains(i))
            .collect();

        let idx = *available.choose(&mut thread_rng())?;
        self.told.insert(idx);

        if self.told.len() >= pool.len() {
            self.told.clear();
        }

        Some(pool[idx])
    }
}

const RUSSIAN_JOKES: &[&str] = &[
    "Пришли как-то программист, сисадмин и тестировщик в бар... Баг закрыли, бар сгорел.",
    "Сколько программистов нужно, чтобы вкрутить лампочку? Ни одного. Это hardware-проблема.",
    "— Доктор, у меня ошибка 404. — А что болит? — Совесть не найдена.",
    "Лучший комментарий в коде — тот, который написан в Jira.",
    "Программист не пишет баги, он создаёт недокументированные фичи.",
    "git commit -m \"исправлено\" — любимая ложь разработчика.",
    "Пришёл как-то NULL в гости к true. — Открыто? — Нет.",
    "Работает? Не трогай. Сломается? Починишь. Горит? Значит, prod.",
    "Билд упал. Стул тоже. Разработчик в космосе.",
    "Если бы архитектура ПО строилась из кирпичей, то каждый второй проект был бы Пизанской башней.",
];

const ENGLISH_JOKES: &[&str] = &[
    "Why do programmers prefer dark mode? Because light attracts bugs.",
    "A QA engineer walks into a bar. Orders 1 beer. Orders 0 beers. Orders 999999 beers. Orders a lizard. Orders -1 beers. The real customer walks in and asks where the bathroom is. The bar bursts into flames.",
    "How many programmers does it take to change a light bulb? None, that's a hardware issue.",
    "I don't test my code. I just commit and pray.",
    "It's not a bug — it's an undocumented feature.",
    "There are only two hard things in computer science: cache invalidation and naming things.",
    "Why did the developer go broke? Because he used up all his cache.",
    "The best way to debug a program is to add print statements. The second best is to ask a rubber duck.",
    "Normal people believe that if it ain't broke, don't fix it. Engineers believe if it ain't broke, it doesn't have enough features yet.",
    "A SQL query goes into a bar, walks up to two tables and asks: 'Can I join you?'",
];
