//! 应用状态管理

use easyremote_common::types::{DeviceId, VerificationCode};
use easyremote_client_core::ClientConfig;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::RwLock;
use tokio::net::UdpSocket;

/// P2P 连接信息
#[derive(Debug, Clone)]
pub struct P2PConnection {
    /// 会话 ID
    pub session_id: String,
    /// 对方设备 ID
    pub peer_device_id: String,
    /// 本地 UDP 端口
    pub local_port: u16,
    /// 对方地址
    pub peer_addr: Option<std::net::SocketAddr>,
    /// 是否已连接
    pub connected: bool,
}

/// 应用状态
pub struct AppState {
    /// 配置
    pub config: ClientConfig,
    /// 当前设备ID
    pub device_id: DeviceId,
    /// 验证码
    pub verification_code: VerificationCode,
    /// 当前登录用户
    pub current_user: Option<CurrentUser>,
    /// 认证令牌
    pub auth_token: Option<String>,
    /// 连接状态
    pub connection_state: ConnectionState,
    /// 当前会话ID
    pub current_session_id: Option<String>,
    /// P2P 连接（用于被控端接收直连数据）
    pub p2p_socket: Option<Arc<UdpSocket>>,
    /// P2P 连接信息
    pub p2p_connection: Option<P2PConnection>,
}

/// 当前用户信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CurrentUser {
    pub id: String,
    pub username: String,
    pub email: Option<String>,
}

/// 连接状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ConnectionState {
    /// 断开连接
    Disconnected,
    /// 正在连接
    Connecting,
    /// 正在进行 P2P 握手
    P2PHandshaking {
        target_device_id: String,
    },
    /// 已连接到设备
    Connected {
        target_device_id: String,
        target_device_name: String,
        connection_type: String, // "p2p" 或 "relay"
    },
    /// 被控制中
    BeingControlled {
        controller_device_id: String,
        connection_type: String, // "p2p" 或 "relay"
    },
}

/// 持久化的认证数据
#[derive(Debug, Serialize, Deserialize)]
struct AuthData {
    server_url: String,
    token: String,
    user: CurrentUser,
}

impl AppState {
    pub fn new() -> Self {
        // 尝试加载已保存的设备ID
        let (device_id, verification_code) = Self::load_or_create_device_id();
        let config = ClientConfig::load();

        // 尝试加载已保存的登录信息
        let (current_user, auth_token) = Self::load_auth_data(&config.server_url);

        Self {
            config,
            device_id,
            verification_code,
            current_user,
            auth_token,
            connection_state: ConnectionState::Disconnected,
            current_session_id: None,
            p2p_socket: None,
            p2p_connection: None,
        }
    }

    fn get_data_dir() -> PathBuf {
        dirs::data_dir()
            .unwrap_or_else(|| std::path::PathBuf::from("."))
            .join("easyremote")
    }

    fn load_or_create_device_id() -> (DeviceId, VerificationCode) {
        let data_path = Self::get_data_dir().join("device.json");

        if data_path.exists() {
            if let Ok(content) = std::fs::read_to_string(&data_path) {
                if let Ok(data) = serde_json::from_str::<DeviceData>(&content) {
                    return (DeviceId(data.device_id), VerificationCode::generate());
                }
            }
        }

        // 创建新的设备ID
        let device_id = DeviceId::generate();
        let verification_code = VerificationCode::generate();

        // 保存设备ID
        if let Some(parent) = data_path.parent() {
            let _ = std::fs::create_dir_all(parent);
        }
        let data = DeviceData {
            device_id: device_id.0.clone(),
        };
        let _ = std::fs::write(&data_path, serde_json::to_string(&data).unwrap());

        (device_id, verification_code)
    }

    /// 加载认证数据（如果服务器地址匹配）
    fn load_auth_data(server_url: &str) -> (Option<CurrentUser>, Option<String>) {
        let auth_path = Self::get_data_dir().join("auth.json");
        
        if auth_path.exists() {
            if let Ok(content) = std::fs::read_to_string(&auth_path) {
                if let Ok(auth_data) = serde_json::from_str::<AuthData>(&content) {
                    // 只有当服务器地址匹配时才恢复登录状态
                    if auth_data.server_url == server_url {
                        tracing::info!("已恢复登录状态: {}", auth_data.user.username);
                        return (Some(auth_data.user), Some(auth_data.token));
                    } else {
                        tracing::info!("服务器地址已变更，需要重新登录");
                    }
                }
            }
        }
        
        (None, None)
    }

    /// 保存认证数据
    pub fn save_auth_data(&self) -> Result<(), std::io::Error> {
        if let (Some(user), Some(token)) = (&self.current_user, &self.auth_token) {
            let auth_path = Self::get_data_dir().join("auth.json");
            
            if let Some(parent) = auth_path.parent() {
                std::fs::create_dir_all(parent)?;
            }
            
            let auth_data = AuthData {
                server_url: self.config.server_url.clone(),
                token: token.clone(),
                user: user.clone(),
            };
            
            std::fs::write(&auth_path, serde_json::to_string(&auth_data).unwrap())?;
            tracing::info!("登录信息已保存");
        }
        Ok(())
    }

    /// 清除认证数据
    pub fn clear_auth_data(&self) {
        let auth_path = Self::get_data_dir().join("auth.json");
        let _ = std::fs::remove_file(&auth_path);
        tracing::info!("登录信息已清除");
    }

    /// 刷新验证码
    pub fn refresh_code(&mut self) -> String {
        self.verification_code.refresh();
        self.verification_code.0.clone()
    }

    /// 设置登录用户并保存
    pub fn set_user(&mut self, user: CurrentUser, token: String) {
        self.current_user = Some(user);
        self.auth_token = Some(token);
        // 保存登录信息
        let _ = self.save_auth_data();
    }

    /// 退出登录并清除保存的数据
    pub fn logout(&mut self) {
        self.current_user = None;
        self.auth_token = None;
        self.clear_auth_data();
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct DeviceData {
    device_id: String,
}

/// 设备信息响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceInfo {
    pub device_id: String,
    pub device_id_formatted: String,
    pub verification_code: String,
    pub device_name: String,
    pub os_type: String,
}

/// 连接设备请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectRequest {
    pub device_id: String,
    pub verification_code: String,
}

/// 历史记录项
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HistoryItem {
    pub id: String,
    pub device_id: String,
    pub device_name: String,
    pub started_at: String,
    pub ended_at: Option<String>,
    pub duration: Option<String>,
    pub connection_type: String,
}
