use serde::Serialize;
use serde_json::Value;
use std::fs;
use std::path::PathBuf;

/// 账号额度查询：复用 Claude Code 登录后落盘的 OAuth 凭据，
/// 调用与 CLI /usage 同源的私有接口 api.anthropic.com/api/oauth/usage。
/// 该接口未公开文档化，未来可能变动（实现方式参考 cc-switch 项目）。

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct QuotaTier {
    /// five_hour / seven_day / seven_day_opus / seven_day_sonnet 或未来新增窗口
    pub name: String,
    /// 已用百分比 0-100
    pub utilization: f64,
    /// 重置时间（ISO 8601）
    pub resets_at: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ExtraUsage {
    pub is_enabled: bool,
    pub monthly_limit: Option<f64>,
    pub used_credits: Option<f64>,
    pub utilization: Option<f64>,
    pub currency: Option<String>,
}

/// 订阅信息，取自 /api/oauth/profile。
/// 注意：官方该接口不返回活跃订阅的「到期/续费」日期（令牌 scope 不含 billing），
/// 故只能呈现套餐、状态、订阅开始日期与试用到期日。
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Subscription {
    /// Max / Pro / 原始 organization_type
    pub plan: String,
    /// active / trialing / canceled 等
    pub status: String,
    /// 订阅开始日期 ISO
    pub started_at: Option<String>,
    /// 试用到期日期 ISO（仅试用期有值）
    pub trial_ends_at: Option<String>,
    /// 速率档位原文，如 default_claude_max_20x
    pub tier: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AccountQuota {
    /// ok | no_credentials | expired | error
    pub status: String,
    pub message: Option<String>,
    pub tiers: Vec<QuotaTier>,
    pub extra_usage: Option<ExtraUsage>,
    pub subscription: Option<Subscription>,
}

impl AccountQuota {
    fn fail(status: &str, message: String) -> Self {
        Self {
            status: status.into(),
            message: Some(message),
            tiers: vec![],
            extra_usage: None,
            subscription: None,
        }
    }
}

fn credentials_path() -> PathBuf {
    dirs::home_dir()
        .unwrap_or_else(|| PathBuf::from("."))
        .join(".claude")
        .join(".credentials.json")
}

/// 读取 access token；返回 Err(状态) 表示凭据缺失或过期
fn read_access_token() -> Result<String, AccountQuota> {
    let raw = fs::read_to_string(credentials_path()).map_err(|_| {
        AccountQuota::fail("no_credentials", "未找到登录凭据，请先在终端中登录 Claude Code".into())
    })?;
    let root: Value = serde_json::from_str(&raw).map_err(|e| {
        AccountQuota::fail("error", format!("凭据文件解析失败: {e}"))
    })?;
    // 兼容两种键名（不同版本的 Claude Code）
    let oauth = root
        .get("claudeAiOauth")
        .or_else(|| root.get("claude.ai_oauth"))
        .ok_or_else(|| {
            AccountQuota::fail("no_credentials", "凭据文件中没有 OAuth 登录信息（可能使用 API Key 模式）".into())
        })?;
    let token = oauth
        .get("accessToken")
        .and_then(Value::as_str)
        .filter(|s| !s.is_empty())
        .ok_or_else(|| AccountQuota::fail("no_credentials", "凭据中没有 accessToken".into()))?;
    // expiresAt 为毫秒时间戳；过期则提示重新登录（CLI 正常使用时会自动续期）
    if let Some(expires_at) = oauth.get("expiresAt").and_then(Value::as_u64) {
        if expires_at < crate::store::now_ms() {
            return Err(AccountQuota::fail(
                "expired",
                "登录凭据已过期，在终端中使用一次 Claude Code 即可自动续期".into(),
            ));
        }
    }
    Ok(token.to_string())
}

fn parse_tier(name: &str, value: &Value) -> Option<QuotaTier> {
    let utilization = value.get("utilization").and_then(Value::as_f64)?;
    Some(QuotaTier {
        name: name.to_string(),
        utilization,
        resets_at: value
            .get("resets_at")
            .and_then(Value::as_str)
            .map(str::to_string),
    })
}

const KNOWN_TIERS: [&str; 4] = ["five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet"];

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ModelInfo {
    pub id: String,
    pub display_name: String,
}

/// 从官方 /v1/models 接口动态拉取可用模型清单（复用 OAuth 凭据，零维护）
pub fn list_models() -> Result<Vec<ModelInfo>, String> {
    let token = read_access_token().map_err(|q| q.message.unwrap_or(q.status))?;
    let body: Value = ureq::get("https://api.anthropic.com/v1/models?limit=50")
        .set("Authorization", &format!("Bearer {token}"))
        .set("anthropic-beta", "oauth-2025-04-20")
        .set("anthropic-version", "2023-06-01")
        .timeout(std::time::Duration::from_secs(10))
        .call()
        .map_err(|e| e.to_string())?
        .into_json()
        .map_err(|e| e.to_string())?;
    let models = body
        .get("data")
        .and_then(Value::as_array)
        .map(|arr| {
            arr.iter()
                .filter_map(|m| {
                    let id = m.get("id").and_then(Value::as_str)?;
                    let display_name = m
                        .get("display_name")
                        .and_then(Value::as_str)
                        .unwrap_or(id);
                    Some(ModelInfo {
                        id: id.to_string(),
                        display_name: display_name.to_string(),
                    })
                })
                .collect::<Vec<_>>()
        })
        .unwrap_or_default();
    Ok(models)
}

/// 拉取订阅信息（/api/oauth/profile）。失败不影响额度查询，返回 None。
fn fetch_subscription(token: &str) -> Option<Subscription> {
    let body: Value = ureq::get("https://api.anthropic.com/api/oauth/profile")
        .set("Authorization", &format!("Bearer {token}"))
        .set("anthropic-beta", "oauth-2025-04-20")
        .set("Accept", "application/json")
        .timeout(std::time::Duration::from_secs(10))
        .call()
        .ok()?
        .into_json()
        .ok()?;
    let account = body.get("account");
    let org = body.get("organization");
    let has_max = account
        .and_then(|a| a.get("has_claude_max"))
        .and_then(Value::as_bool)
        .unwrap_or(false);
    let has_pro = account
        .and_then(|a| a.get("has_claude_pro"))
        .and_then(Value::as_bool)
        .unwrap_or(false);
    let org_type = org
        .and_then(|o| o.get("organization_type"))
        .and_then(Value::as_str);
    let plan = if has_max {
        "Max".to_string()
    } else if has_pro {
        "Pro".to_string()
    } else {
        org_type.unwrap_or("—").to_string()
    };
    let str_field = |obj: Option<&Value>, key: &str| {
        obj.and_then(|o| o.get(key))
            .and_then(Value::as_str)
            .map(str::to_string)
    };
    Some(Subscription {
        plan,
        status: str_field(org, "subscription_status").unwrap_or_default(),
        started_at: str_field(org, "subscription_created_at"),
        trial_ends_at: str_field(org, "claude_code_trial_ends_at"),
        tier: str_field(org, "rate_limit_tier"),
    })
}

pub fn query_account_quota() -> AccountQuota {
    let token = match read_access_token() {
        Ok(t) => t,
        Err(q) => return q,
    };
    // 订阅信息与额度查询并发：两接口各 10s 超时，串行最坏 ~20s，并发降到 ~10s
    let sub_token = token.clone();
    let sub_handle = std::thread::spawn(move || fetch_subscription(&sub_token));
    let resp = ureq::get("https://api.anthropic.com/api/oauth/usage")
        .set("Authorization", &format!("Bearer {token}"))
        .set("anthropic-beta", "oauth-2025-04-20")
        .set("Accept", "application/json")
        .timeout(std::time::Duration::from_secs(10))
        .call();
    let body: Value = match resp {
        Ok(r) => match r.into_json() {
            Ok(v) => v,
            Err(e) => return AccountQuota::fail("error", format!("响应解析失败: {e}")),
        },
        Err(ureq::Error::Status(401 | 403, _)) => {
            return AccountQuota::fail("expired", "鉴权失败，请在终端中重新登录 Claude Code".into())
        }
        Err(ureq::Error::Status(code, r)) => {
            let text = r.into_string().unwrap_or_default();
            return AccountQuota::fail("error", format!("接口错误 HTTP {code}: {text}"));
        }
        Err(e) => return AccountQuota::fail("error", format!("网络错误: {e}")),
    };

    let mut tiers = Vec::new();
    // 已知窗口按固定顺序，未知窗口附后（接口可能新增窗口类型）
    for name in KNOWN_TIERS {
        if let Some(v) = body.get(name) {
            if let Some(t) = parse_tier(name, v) {
                tiers.push(t);
            }
        }
    }
    if let Some(obj) = body.as_object() {
        for (key, value) in obj {
            if key == "extra_usage" || KNOWN_TIERS.contains(&key.as_str()) {
                continue;
            }
            if let Some(t) = parse_tier(key, value) {
                tiers.push(t);
            }
        }
    }

    let extra_usage = body.get("extra_usage").map(|e| ExtraUsage {
        is_enabled: e.get("is_enabled").and_then(Value::as_bool).unwrap_or(false),
        monthly_limit: e.get("monthly_limit").and_then(Value::as_f64),
        used_credits: e.get("used_credits").and_then(Value::as_f64),
        utilization: e.get("utilization").and_then(Value::as_f64),
        currency: e.get("currency").and_then(Value::as_str).map(str::to_string),
    });

    // 等待并发的订阅查询线程；线程 panic 则按无订阅处理
    let subscription = sub_handle.join().unwrap_or(None);
    AccountQuota {
        status: "ok".into(),
        message: None,
        tiers,
        extra_usage,
        subscription,
    }
}
