// File: src/app.rs
// Author: Hadi Cahyadi <cumulus13@gmail.com>

use anyhow::Result;
use ratatui::{backend::Backend, Terminal};
use std::time::{Duration, Instant};

use crate::{audio::WasapiMixer, input::{self, Action}, ui};

const REFRESH_INTERVAL: Duration = Duration::from_millis(100);
const INPUT_POLL_TIMEOUT: Duration = Duration::from_millis(50);

pub struct App {
    pub mixer: WasapiMixer,
    pub selected: usize,
    pub running: bool,
    pub last_refresh: Instant,
    pub status_msg: Option<String>,
}

impl App {
    pub fn new() -> Result<Self> {
        let mixer = WasapiMixer::new()?;
        Ok(Self {
            mixer,
            selected: 0,
            running: true,
            last_refresh: Instant::now(),
            status_msg: None,
        })
    }

    pub fn run<B: Backend>(&mut self, terminal: &mut Terminal<B>) -> Result<()> {
        let mut channels = self.mixer.snapshot().unwrap_or_default();
        if channels.is_empty() {
            self.status_msg = Some("No audio devices found.".to_string());
        }

        terminal.draw(|f| ui::render(f, &channels, self.selected, self.status_msg.as_deref()))?;

        while self.running {
            let action = input::poll_action(INPUT_POLL_TIMEOUT);

            match action {
                Action::Quit => self.running = false,

                Action::SelectNext => {
                    if !channels.is_empty() {
                        // Wrap around: last → first
                        self.selected = (self.selected + 1) % channels.len();
                    }
                }

                Action::SelectPrev => {
                    if !channels.is_empty() {
                        // Wrap around: first → last
                        self.selected = if self.selected == 0 {
                            channels.len() - 1
                        } else {
                            self.selected - 1
                        };
                    }
                }

                Action::VolumeUp => {
                    // Use the live channel data (just refreshed below)
                    if let Some(ch) = channels.get(self.selected) {
                        let _ = self.mixer.adjust_volume(ch, 5);
                    }
                }

                Action::VolumeDown => {
                    if let Some(ch) = channels.get(self.selected) {
                        let _ = self.mixer.adjust_volume(ch, -5);
                    }
                }

                Action::ToggleMute => {
                    if let Some(ch) = channels.get(self.selected) {
                        let _ = self.mixer.toggle_mute(ch);
                    }
                }

                Action::None => {}
            }

            // Always refresh after an action, or on the periodic timer
            let need_refresh = action != Action::None
                || self.last_refresh.elapsed() >= REFRESH_INTERVAL;

            if need_refresh {
                let fresh = self.mixer.snapshot().unwrap_or_default();

                // Update status message only on the first empty→non-empty transition
                if fresh.is_empty() && self.status_msg.is_none() {
                    self.status_msg = Some("No audio devices found.".to_string());
                } else if !fresh.is_empty() && self.status_msg.as_deref() == Some("No audio devices found.") {
                    self.status_msg = None;
                }

                channels = fresh;

                // Keep selection in bounds after a channel disappears
                if !channels.is_empty() && self.selected >= channels.len() {
                    self.selected = channels.len() - 1;
                }

                self.last_refresh = Instant::now();
                terminal.draw(|f| {
                    ui::render(f, &channels, self.selected, self.status_msg.as_deref())
                })?;
            }
        }
        Ok(())
    }
}
