//! 微信 ClawBot 凭据持久化。
//!
//! bot_token 是能向本机 Claude Code 会话写入指令的"遥控密钥"，与只读的
//! ~/.claude/.credentials.json（Claude OAuth）刻意分开存放，单独落盘到
//! %APPDATA%/ccgui/wechat.json，便于权限管控与一键解绑（删文件即解绑）。

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

/// 扫码登录后获得并需要长期持有的凭据。
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Creds {
    /// 登录令牌，所有后续请求的 Authorization: Bearer
    pub token: String,
    /// 登录返回的基址（可能因 IDC 重定向不同于默认域名），后续请求一律用它
    pub base_url: String,
    /// 账号标识（ilink_user_id 等），仅作展示/区分
    #[serde(default)]
    pub account_id: String,
    /// 绑定微信昵称（若服务端返回），用于设置页展示
    #[serde(default)]
    pub nick: String,
    /// 长轮询去重游标 get_updates_buf：必须随 token 一起持久化、重启续传
    #[serde(default)]
    pub cursor: String,
    /// 已激活的操作人 from_user_id（用户首次给 bot 发消息后记下，出站通知发给它）
    #[serde(default)]
    pub operator: Option<String>,
}

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

/// 读取凭据；文件不存在或损坏时返回 None（视为未绑定）
pub fn load() -> Option<Creds> {
    let raw = fs::read_to_string(creds_path()).ok()?;
    let creds: Creds = serde_json::from_str(&raw).ok()?;
    if creds.token.is_empty() {
        None
    } else {
        Some(creds)
    }
}

/// 落盘凭据（原子写）
pub fn save(creds: &Creds) -> Result<(), String> {
    let raw = serde_json::to_string_pretty(creds).map_err(|e| e.to_string())?;
    crate::fsx::write_atomic(&creds_path(), raw.as_bytes())
}

/// 删除凭据文件（解绑）
pub fn clear() {
    let _ = fs::remove_file(creds_path());
}
