durak 2.0.0

tui card game 'durak'(fool) built with ratatui.
use super::render::render_ui;
use super::state::AppState;
use crate::game::{AiDifficulty, AiPlayer, GamePhase, GameState};
use crate::ui::debug_overlay::{debug, error, info};
use crossterm::ExecutableCommand;
use crossterm::terminal::{LeaveAlternateScreen, disable_raw_mode};
use ratatui::Terminal;
use ratatui::backend::Backend;
use std::io::{self, stdout};
pub struct App {
    pub game_state: GameState,
    pub app_state: AppState,
    pub selected_card_idx: Option<usize>,
    pub selected_cards: Vec<usize>,
    pub should_quit: bool,
    pub show_debug: bool,
    pub multiple_selection_mode: bool,
    pub ai_player: AiPlayer,
    pub selected_difficulty: AiDifficulty,
}
impl App {
    pub fn new() -> Self {
        info("Creating new App instance");
        Self {
            game_state: GameState::new(),
            app_state: AppState::MainMenu,
            selected_card_idx: None,
            selected_cards: Vec::new(),
            ai_player: AiPlayer::new(AiDifficulty::Medium),
            selected_difficulty: AiDifficulty::Medium,
            should_quit: false,
            show_debug: false,
            multiple_selection_mode: false,
        }
    }
    pub fn safe_exit(&mut self, error_msg: Option<&str>) -> io::Result<()> {
        self.should_quit = true;
        if let Some(msg) = error_msg {
            error(format!("Game error: {}", msg));
        }
        disable_raw_mode()?;
        stdout().execute(LeaveAlternateScreen)?;
        if let Some(msg) = error_msg {
            eprintln!("Error: {}", msg);
        }
        Ok(())
    }
    pub fn toggle_debug(&mut self) {
        self.show_debug = !self.show_debug;
    }
    pub fn quit(&mut self) {
        if let Err(e) = self.safe_exit(None) {
            error(format!("Failed to restore terminal during quit: {}", e));
        }
    }
    #[inline]
    pub fn show_rules(&mut self) {
        self.app_state = AppState::RulesPage;
    }
    #[inline]
    pub fn return_to_menu(&mut self) {
        self.app_state = AppState::MainMenu;
    }
    #[inline]
    pub fn show_difficulty_select(&mut self) {
        self.app_state = AppState::DifficultySelect;
    }
    pub fn select_difficulty(&mut self, difficulty: AiDifficulty) {
        self.selected_difficulty = difficulty;
        self.ai_player = AiPlayer::new(difficulty);
        info(format!("AI difficulty changed to: {}", difficulty));
        self.app_state = AppState::MainMenu;
    }
    pub fn toggle_multiple_selection(&mut self) {
        self.multiple_selection_mode = !self.multiple_selection_mode;
        if !self.multiple_selection_mode {
            self.selected_card_idx = None;
        }
    }
    pub fn toggle_card_selection(&mut self, card_idx: usize) {
        if let Some(pos) = self.selected_cards.iter().position(|&idx| idx == card_idx) {
            self.selected_cards.remove(pos);
            debug(format!("Deselected card at index {}", card_idx));
        } else {
            self.selected_cards.push(card_idx);
            debug(format!("Selected card at index {}", card_idx));
        }
    }
    pub fn current_player_index(&self) -> usize {
        match *self.game_state.game_phase() {
            GamePhase::Attack => self.game_state.current_attacker(),
            GamePhase::Defense => self.game_state.current_defender(),
            _ => self.game_state.current_attacker(),
        }
    }
    pub fn render<B: Backend>(&self, terminal: &mut Terminal<B>) -> io::Result<()> {
        terminal.draw(|f| render_ui(self, f))?;
        Ok(())
    }
}