//! 移动端网关凭据：配对 token 落盘 %APPDATA%/ccgui/mobile.json（删文件即解绑）

use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;

#[derive(Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct MobileCreds {
    /// 设备配对令牌；手机在 hello 帧携带，与此比对
    pub token: String,
    /// 公网中继房间号：CCGUI 拨出时以此注册，手机用同一房间号加入（不同电脑各自房间，互不冲突）
    #[serde(default)]
    pub room: String,
}

fn creds_path() -> PathBuf {
    dirs::config_dir()
        .unwrap_or_else(|| PathBuf::from("."))
        .join("ccgui")
        .join("mobile.json")
}

/// 读取 token；不存在则生成随机 token 落盘（首次启用时）
pub fn load_or_init_token() -> String {
    let path = creds_path();
    if let Ok(raw) = fs::read_to_string(&path) {
        if let Ok(c) = serde_json::from_str::<MobileCreds>(&raw) {
            if !c.token.is_empty() {
                return c.token;
            }
        }
    }
    let token = gen_token();
    let _ = save_token(&token);
    token
}

/// 读取整份凭据（token + room），不存在则用默认值
fn load_creds() -> MobileCreds {
    fs::read_to_string(creds_path())
        .ok()
        .and_then(|raw| serde_json::from_str::<MobileCreds>(&raw).ok())
        .unwrap_or_default()
}

fn save_creds(c: &MobileCreds) -> std::io::Result<()> {
    let path = creds_path();
    if let Some(dir) = path.parent() {
        fs::create_dir_all(dir)?;
    }
    let json = serde_json::to_string_pretty(c).unwrap_or_default();
    fs::write(&path, json)
}

pub fn save_token(token: &str) -> std::io::Result<()> {
    let mut c = load_creds();
    c.token = token.to_string();
    save_creds(&c)
}

/// 读取中继房间号；不存在则生成随机房间号落盘（与 token 同文件）
pub fn load_or_init_room() -> String {
    let mut c = load_creds();
    if c.room.is_empty() {
        c.room = gen_token();
        let _ = save_creds(&c);
    }
    c.room
}

/// 解绑：删除凭据文件（下次启用会重新生成新 token）
pub fn unbind() {
    let _ = fs::remove_file(creds_path());
}

fn gen_token() -> String {
    uuid::Uuid::new_v4().simple().to_string()
}
