//! Ratatui-based terminal user interface for Arc Package Manager

use crossterm::{
    event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{
    backend::{Backend, CrosstermBackend},
    layout::{Alignment, Constraint, Direction, Layout},
    style::{Color, Modifier, Style},
    text::{Line, Span},
    widgets::{Block, Borders, Gauge, Paragraph, Wrap},
    Terminal,
};
use std::{
    error::Error,
    io,
    sync::{Arc, Mutex},
    time::Duration,
};

use libarc::progress::{ProgressCallback, ProgressState};

/// State for the TUI application
#[allow(dead_code)]
pub struct App {
    progress_state: Arc<Mutex<ProgressState>>,
    message: String,
    should_quit: bool,
}

impl App {
    #[allow(dead_code)]
    /// Create a new TUI application
    pub fn new() -> Self {
        Self {
            progress_state: Arc::new(Mutex::new(ProgressState::Preparing)),
            message: String::new(),
            should_quit: false,
        }
    }

    #[allow(dead_code)]
    /// Get a progress callback for this app
    pub fn progress_callback(&self) -> Arc<TuiProgressCallback> {
        Arc::new(TuiProgressCallback {
            state: Arc::clone(&self.progress_state),
        })
    }

    #[allow(dead_code)]
    /// Handle user input
    pub fn handle_input(&mut self) {
        if let Ok(true) = event::poll(Duration::from_millis(100)) {
            if let Ok(Event::Key(key)) = event::read() {
                match key.code {
                    KeyCode::Char('q') | KeyCode::Esc => self.should_quit = true,
                    _ => {}
                }
            }
        }
    }

    #[allow(dead_code)]
    /// Update the message
    pub fn set_message(&mut self, msg: String) {
        self.message = msg;
    }

    #[allow(dead_code)]
    /// Check if the app should quit
    pub fn should_quit(&self) -> bool {
        self.should_quit
    }
}

impl Default for App {
    fn default() -> Self {
        Self::new()
    }
}

/// Progress callback implementation for TUI
#[allow(dead_code)]
pub struct TuiProgressCallback {
    state: Arc<Mutex<ProgressState>>,
}

impl ProgressCallback for TuiProgressCallback {
    fn update(&self, state: ProgressState) {
        if let Ok(mut current) = self.state.lock() {
            *current = state;
        }
    }
}

/// Terminal UI manager
#[allow(dead_code)]
pub struct Tui<B: Backend> {
    terminal: Terminal<B>,
    app: App,
}

impl Tui<CrosstermBackend<io::Stdout>> {
    #[allow(dead_code)]
    /// Create a new TUI instance
    pub fn new() -> Result<Self, Box<dyn Error>> {
        enable_raw_mode()?;
        let mut stdout = io::stdout();
        execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
        let backend = CrosstermBackend::new(stdout);
        let terminal = Terminal::new(backend)?;

        Ok(Tui {
            terminal,
            app: App::new(),
        })
    }

    #[allow(dead_code)]
    /// Get a mutable reference to the app
    pub fn app_mut(&mut self) -> &mut App {
        &mut self.app
    }

    #[allow(dead_code)]
    /// Get a reference to the app
    pub fn app(&self) -> &App {
        &self.app
    }

    #[allow(dead_code)]
    /// Draw the UI
    pub fn draw(&mut self) -> Result<(), Box<dyn Error>> {
        self.terminal.draw(|f| ui(f, &self.app))?;
        Ok(())
    }

    #[allow(dead_code)]
    /// Handle input and draw
    pub fn handle_events(&mut self) {
        self.app.handle_input();
    }

    #[allow(dead_code)]
    /// Exit the TUI
    pub fn exit(&mut self) -> Result<(), Box<dyn Error>> {
        disable_raw_mode()?;
        execute!(
            self.terminal.backend_mut(),
            LeaveAlternateScreen,
            DisableMouseCapture
        )?;
        self.terminal.show_cursor()?;
        Ok(())
    }
}

/// Draw the UI
#[allow(dead_code)]
fn ui(f: &mut ratatui::Frame, app: &App) {
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .margin(2)
        .constraints(
            [
                Constraint::Length(3),
                Constraint::Min(10),
                Constraint::Length(3),
            ]
            .as_ref(),
        )
        .split(f.area());

    // Title
    let title = Paragraph::new("Arc Package Manager")
        .style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD))
        .alignment(Alignment::Center);
    f.render_widget(title, chunks[0]);

    // Main content area with progress
    let progress_state = app.progress_state.lock().unwrap();
    let content = match progress_state.clone() {
        ProgressState::Preparing => {
            Paragraph::new("Preparing installation...")
                .block(Block::default().borders(Borders::ALL).title("Status"))
                .style(Style::default().fg(Color::Yellow))
        }
        ProgressState::Downloading { current, total } => {
            let progress = if total > 0 {
                (current as f64 / total as f64) * 100.0
            } else {
                0.0
            };
            let gauge = Gauge::default()
                .block(Block::default().borders(Borders::ALL).title("Downloading"))
                .gauge_style(Style::default().fg(Color::Green).add_modifier(Modifier::BOLD))
                .percent(progress as u16)
                .label(format!("{}/{} packages", current, total));
            f.render_widget(gauge, chunks[1]);
            return;
        }
        ProgressState::Installing { current, total } => {
            let progress = if total > 0 {
                (current as f64 / total as f64) * 100.0
            } else {
                0.0
            };
            let gauge = Gauge::default()
                .block(Block::default().borders(Borders::ALL).title("Installing"))
                .gauge_style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD))
                .percent(progress as u16)
                .label(format!("{}/{} packages", current, total));
            f.render_widget(gauge, chunks[1]);
            return;
        }
        ProgressState::Completed => {
            Paragraph::new("Installation completed successfully!")
                .block(Block::default().borders(Borders::ALL).title("Status"))
                .style(Style::default().fg(Color::Green).add_modifier(Modifier::BOLD))
        }
        ProgressState::Failed(ref err) => {
            Paragraph::new(format!("Error: {}", err))
                .block(Block::default().borders(Borders::ALL).title("Status"))
                .style(Style::default().fg(Color::Red).add_modifier(Modifier::BOLD))
                .wrap(Wrap { trim: true })
        }
    };
    f.render_widget(content, chunks[1]);

    // Footer
    let footer_text = vec![
        Line::from(vec![
            Span::styled("Press ", Style::default()),
            Span::styled("q", Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD)),
            Span::styled(" to quit", Style::default()),
        ]),
    ];
    let footer = Paragraph::new(footer_text)
        .style(Style::default().fg(Color::DarkGray))
        .alignment(Alignment::Center);
    f.render_widget(footer, chunks[2]);
}
