// types.ts — 数据层契约（mock / http 双实现共用）

export type Plan = 'free' | 'pro';

export interface Session {
  /** access token：仅存内存,绝不落盘 */
  accessToken: string;
  /** refresh token：localStorage(header token 方案,见 README 取舍说明) */
  refreshToken: string;
  /** access 过期时间戳(ms) */
  accessExpiresAt: number;
}

export interface Me {
  email: string;
  plan: Plan;
  /** PRO 到期日 YYYY-MM-DD;免费版为 null */
  expiresAt: string | null;
  devicesUsed: number;
  devicesMax: number;
  /** 今日剩余时长(分钟);PRO 为 null 表示不限 */
  quotaTodayMin: number | null;
  dataTodayGB: number;
  /** 近 7 日流量(GB) */
  weeklyGB: number[];
  totpEnabled: boolean;
}

export interface SubscriptionInfo {
  url: string;
}

export interface Device {
  id: string;
  name: string;
  platform: string;
  lastActive: string;
  current: boolean;
}

export interface RedeemResult {
  plan: Plan;
  expiresAt: string | null;
}

export interface TotpSetup {
  /** base32 密钥 */
  secret: string;
  /** otpauth:// URI(可渲染二维码) */
  otpauthUri: string;
}

/** 统一错误体 —— 与后端约定 {code, message_zh, message_en} */
export interface ApiErrorBody {
  code: string;
  message_zh: string;
  message_en: string;
}

export class ApiError extends Error {
  code: string;
  message_zh: string;
  message_en: string;
  /** 锁定类错误：剩余秒数 */
  retryAfter?: number;
  constructor(body: ApiErrorBody, retryAfter?: number) {
    super(body.code);
    this.name = 'ApiError';
    this.code = body.code;
    this.message_zh = body.message_zh;
    this.message_en = body.message_en;
    this.retryAfter = retryAfter;
  }
}

/** 登录第一段结果：成功直接给 session,或要求二段 TOTP */
export type LoginResult =
  | { kind: 'session'; session: Session }
  | { kind: 'totp_required'; pendingToken: string };

export interface ApiClient {
  login(email: string, password: string): Promise<LoginResult>;
  /** 登录二段式：提交 TOTP 动态码换取 session */
  loginTotp(pendingToken: string, code: string): Promise<Session>;
  refresh(): Promise<Session>;
  getMe(): Promise<Me>;
  getSubscription(): Promise<SubscriptionInfo>;
  resetSubscription(): Promise<SubscriptionInfo>;
  listDevices(): Promise<Device[]>;
  removeDevice(id: string): Promise<void>;
  redeem(code: string): Promise<RedeemResult>;
  totpSetup(): Promise<TotpSetup>;
  totpVerify(code: string): Promise<void>;
  totpDisable(code: string): Promise<void>;
  logout(): Promise<void>;
}
