use serde::Serialize;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tauri::{AppHandle, Emitter};

use super::{AuthManager, User};

// Verification interval (5 minutes)
const VERIFICATION_INTERVAL_MS: u64 = 300000;

/// Session verification result event emitted to frontend
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase", tag = "type")]
pub enum SessionVerificationEvent {
    Verified { user: User },
    NeedsReauth { reason: String },
    NetworkError { message: String },
}

/// Background session verifier
pub struct SessionVerifier {
    auth_manager: Arc<AuthManager>,
    is_running: Arc<AtomicBool>,
    device_id: String,
    app_handle: Option<AppHandle>,
}

impl SessionVerifier {
    /// Create a new session verifier
    pub fn new(auth_manager: Arc<AuthManager>, device_id: String) -> Self {
        Self {
            auth_manager,
            is_running: Arc::new(AtomicBool::new(false)),
            device_id,
            app_handle: None,
        }
    }

    /// Set the Tauri app handle for event emission
    pub fn set_app_handle(&mut self, app_handle: AppHandle) {
        self.app_handle = Some(app_handle);
    }

    /// Start periodic session verification
    pub async fn start(&self) {
        if self.is_running.swap(true, Ordering::SeqCst) {
            log::info!("[SessionVerifier] Already running");
            return;
        }

        log::info!("[SessionVerifier] Starting background verification");

        let auth_manager = Arc::clone(&self.auth_manager);
        let is_running = Arc::clone(&self.is_running);
        let device_id = self.device_id.clone();
        let app_handle = self.app_handle.clone();

        tokio::spawn(async move {
            // Initial verification after short delay
            tokio::time::sleep(Duration::from_millis(2000)).await;

            while is_running.load(Ordering::SeqCst) {
                // Get current session
                let session = auth_manager.get_session().await;

                if let Some(session) = session {
                    log::debug!(
                        "[SessionVerifier] Verifying session for: {}",
                        session.username
                    );

                    // Verify the session
                    match auth_manager
                        .verify_session(
                            &session.server_url,
                            &session.user_id,
                            &session.access_token,
                            &device_id,
                        )
                        .await
                    {
                        Ok(user) => {
                            log::info!("[SessionVerifier] Session verified successfully");

                            // Emit success event
                            if let Some(app) = &app_handle {
                                let event = SessionVerificationEvent::Verified { user };
                                if let Err(e) = app.emit("auth:session-verified", event) {
                                    log::error!("[SessionVerifier] Failed to emit event: {}", e);
                                }
                            }

                            // Update session as verified
                            let mut updated_session = session;
                            updated_session.verified = true;
                            updated_session.needs_reauth = false;
                            auth_manager.set_session(Some(updated_session)).await;
                        }
                        Err(e) => {
                            log::warn!("[SessionVerifier] Verification failed: {}", e);

                            // Classify error
                            let is_auth_error = e.contains("401") || e.contains("403");
                            let is_network_error = e.contains("network")
                                || e.contains("timeout")
                                || e.contains("connection")
                                || e.contains("DNS");

                            if is_auth_error {
                                // Token is invalid - need re-authentication
                                log::warn!("[SessionVerifier] Session requires re-authentication");

                                if let Some(app) = &app_handle {
                                    let event = SessionVerificationEvent::NeedsReauth {
                                        reason: "Session expired".to_string(),
                                    };
                                    if let Err(e) = app.emit("auth:needs-reauth", event) {
                                        log::error!(
                                            "[SessionVerifier] Failed to emit event: {}",
                                            e
                                        );
                                    }
                                }

                                // Update session
                                let mut updated_session = session;
                                updated_session.verified = false;
                                updated_session.needs_reauth = true;
                                auth_manager.set_session(Some(updated_session)).await;
                            } else if is_network_error {
                                // Network error - keep using cached session
                                log::info!("[SessionVerifier] Network error during verification, keeping cached session");

                                if let Some(app) = &app_handle {
                                    let event = SessionVerificationEvent::NetworkError {
                                        message: e.clone(),
                                    };
                                    if let Err(e) = app.emit("auth:network-error", event) {
                                        log::error!(
                                            "[SessionVerifier] Failed to emit event: {}",
                                            e
                                        );
                                    }
                                }
                            } else {
                                // Unknown error - log but don't invalidate
                                log::error!(
                                    "[SessionVerifier] Unknown error during verification: {}",
                                    e
                                );
                            }
                        }
                    }
                }

                // Wait for next verification
                tokio::time::sleep(Duration::from_millis(VERIFICATION_INTERVAL_MS)).await;
            }

            log::info!("[SessionVerifier] Stopped");
        });
    }

    /// Stop periodic verification
    pub fn stop(&self) {
        log::info!("[SessionVerifier] Stopping background verification");
        self.is_running.store(false, Ordering::SeqCst);
    }
}
