// 与 Rust 侧 serde 结构一一对应的类型定义

export interface ProjectEntry {
  path: string
  name: string
}

export interface Category {
  id: string
  name: string
  order: number
}

export interface CommandItem {
  id: string
  name: string
  content: string
  categoryId: string | null
  /** null = 所有项目可见，否则仅在列出的项目路径下可见 */
  projects: string[] | null
  /** 加星的指令靠前显示 */
  starred: boolean
  updatedAt: number
}

export interface RuleItem {
  id: string
  name: string
  content: string
  categoryId: string | null
  updatedAt: number
}

export interface Settings {
  theme: 'system' | 'light' | 'dark'
  closeToTray: boolean
  notifyOnAttention: boolean
  notifyOnDone: boolean
  hookPort: number
  /** claude 可执行文件路径；空串表示自动检测 */
  claudePath: string
  /** 启用代码索引（符号图谱）并为项目注册 ccgui-index MCP 服务器 */
  indexEnabled: boolean
  /** 启用微信 ClawBot 对接（扫码后长轮询收发消息） */
  wechatEnabled: boolean
  /** 允许微信入站消息驱动会话（写入/入队）；关闭则只收通知、不接受遥控 */
  wechatRemoteInput: boolean
  /** 推送：会话等待权限确认 */
  wechatPushAttention: boolean
  /** 推送：回合完成摘要 */
  wechatPushDone: boolean
  /** 推送：账号额度告警 */
  wechatPushQuota: boolean
  /** 启用移动端 App 远程映射网关（局域网 WebSocket，实时镜像终端） */
  mobileEnabled: boolean
  /** 允许移动端进行文件管理（浏览/编辑/复制/删除等；删除走回收站）。默认关闭 */
  mobileFsEnabled: boolean
  /** 移动端网关监听端口 */
  mobilePort: number
  /** 启用公网中继拨出：CCGUI 主动连到境内 VPS 中继，供手机在外网远程访问 */
  mobileRelayEnabled: boolean
  /** 中继地址（形如 wss://relay.你的域名/） */
  mobileRelayUrl: string
  /** 启用公网隧道（子域名反向代理；需同时开启公网中继） */
  tunnelEnabled: boolean
  /** 隧道注册密钥（= 中继的 TUNNEL_SECRET） */
  tunnelSecret: string
  /** 隧道映射清单 */
  tunnelMappings: TunnelMapping[]
}

/** 隧道映射：子域名前缀 <-> 本机本地端口 */
export interface TunnelMapping {
  id: string
  subdomain: string
  localPort: number
  enabled: boolean
}

/** 微信 ClawBot 绑定状态（设置页轮询展示） */
export interface WechatStatus {
  enabled: boolean
  /** off / await_scan / scanned / bound / expired / error */
  phase: string
  bound: boolean
  nick: string
  /** 操作人已激活（已有 context_token，可推送/回复） */
  operatorActive: boolean
  /** 二维码 data URL（未绑定且处于扫码流程时有值） */
  qrDataUrl: string
  message: string
}

/** 微信入站消息（后端 wechat-inbound 事件载荷） */
export interface WechatInbound {
  userId: string
  text: string
  /** 图片消息时为已下载落盘的本地路径 */
  imagePath: string
}

/** 单项目代码索引状态 */
export interface IndexStatus {
  indexing: boolean
  files: number
  symbols: number
  lastError: string | null
  updatedAt: number
}

export interface ClaudePathInfo {
  /** 实际将执行的命令（兜底时为 "claude"） */
  display: string
  source: 'manual' | 'manual-invalid' | 'path' | 'known' | 'fallback'
}

export interface Config {
  projects: ProjectEntry[]
  commands: CommandItem[]
  commandCategories: Category[]
  rules: RuleItem[]
  ruleCategories: Category[]
  titleOverrides: Record<string, string>
  seeded: boolean
  seededVersion: number
  settings: Settings
}

export interface FsEntry {
  name: string
  path: string
  isDir: boolean
  /** 字节数；目录为 0（移动端文件管理引入，桌面端暂未展示） */
  size?: number
  /** 修改时间（Unix 毫秒）；读取失败为 0 */
  mtimeMs?: number
}

export interface UsageBucket {
  inputTokens: number
  outputTokens: number
  cacheReadTokens: number
  cacheCreationTokens: number
  costUsd: number
}

export interface UsageStats {
  day: UsageBucket
  week: UsageBucket
  month: UsageBucket
}

export interface QuotaTier {
  name: string
  /** 已用百分比 0-100 */
  utilization: number
  resetsAt: string | null
}

export interface ExtraUsage {
  isEnabled: boolean
  monthlyLimit: number | null
  usedCredits: number | null
  utilization: number | null
  currency: string | null
}

/** 订阅信息（来自 /api/oauth/profile，官方未提供活跃订阅的到期日，故以开始日呈现） */
export interface Subscription {
  /** Max / Pro / 原始 organization_type */
  plan: string
  /** active / trialing / canceled 等 */
  status: string
  /** 订阅开始日期 ISO，可能为空 */
  startedAt: string | null
  /** 试用到期日期 ISO，仅试用期有值 */
  trialEndsAt: string | null
  /** 速率档位原文，如 default_claude_max_20x */
  tier: string | null
}

export interface AccountQuota {
  status: 'ok' | 'no_credentials' | 'expired' | 'error'
  message: string | null
  tiers: QuotaTier[]
  extraUsage: ExtraUsage | null
  subscription: Subscription | null
}

export interface SessionInfo {
  id: string
  title: string
  mtime: number
  size: number
}

export interface PreviewMessage {
  role: 'user' | 'assistant' | 'tool'
  text: string
}

export interface SearchHit {
  projectPath: string
  sessionId: string
  title: string
  snippet: string
  mtime: number
}

export interface InjectedRule {
  slug: string
  enabled: boolean
}

export interface OpenProjectPayload {
  path: string
  isNew: boolean
}

export interface HookEventPayload {
  event: string
  sessionId: string
  cwd: string
  message: string
  /** Stop 事件时为最后一条回复的摘要 */
  summary: string
  /** Stop 事件时为会话当前实际使用的模型 ID */
  model: string
  /** Stop 事件时为本回合是否使用了扩展思考 */
  thinking: boolean
  /** Stop 事件时为从会话记录解析出的标题（自动名，未应用覆盖名）；其他事件为空 */
  title: string
}

export interface SessionMeta {
  model: string
  thinking: boolean
}

export interface FilePreviewData {
  kind: 'text' | 'markdown' | 'image' | 'binary' | 'toolarge'
  content: string
  mime: string
  mtimeMs: number
  size: number
}

export interface ModelInfo {
  id: string
  displayName: string
}

/** API 注入：自定义模型接口 */
export interface ApiEndpoint {
  /** 空串表示新建（保存时由后端生成） */
  id: string
  name: string
  baseUrl: string
  key: string
  /** 首选模型：直连注入时写入 settings */
  model: string
  /** 该接口参与路由的模型清单（路由模式聚合用） */
  models: string[]
}

/** API 注入：Claude Code 当前全局接口状态 */
export interface ApiStatus {
  /** 自定义接口地址；null = 官方默认 */
  baseUrl: string | null
  /** Key 掩码（前6…后4）；null = 未设置 */
  keyMasked: string | null
  /** 当前生效的模型 */
  model: string | null
  /** 未配置任何自定义接口/Key */
  isOfficial: boolean
  /** 本工具记录的注入来源接口 id（用于列表高亮"使用中"） */
  injectedEndpointId: string | null
  /** 三态：official（官方）/ direct（直连）/ router（多模型路由代理） */
  mode: 'official' | 'direct' | 'router'
}

/** 路由表条目：对外模型名 → 某接口的真实模型名 */
export interface RouteRule {
  id: string
  /** 对外模型名（claude 侧可见；禁用保留别名 sonnet/opus/haiku/fable） */
  alias: string
  endpointId: string
  /** 转发时改写进请求体的真实模型名 */
  model: string
}

/** 路由代理配置 */
export interface RouterConfig {
  /** 首选端口（被占用时系统分配并回写） */
  port: number
  /** 占位鉴权 token（系统生成，只读展示） */
  token: string
  /** 默认接口 id：未命中路由的请求透传到它 */
  defaultEndpointId: string
  /** 主模型 alias：路由注入时写入 settings */
  mainAlias: string
  /** subagent 兜底模型：非空写 CLAUDE_CODE_SUBAGENT_MODEL */
  subagentModel: string
}

/** 代理运行状态 */
export interface RouterStatus {
  running: boolean
  port: number
  logCount: number
}

/** 路由面板一次性视图 */
export interface RouterView {
  config: RouterConfig
  routes: RouteRule[]
  endpoints: ApiEndpoint[]
  proxy: RouterStatus
}

/** 代理请求日志条目 */
export interface RequestLog {
  ts: string
  method: string
  url: string
  modelIn: string
  routedTo: string
  modelOut: string
  status: number
  elapsedMs: number
  error: string
}

/** Agent 定义（~/.claude/agents/*.md 或项目级 .claude/agents/*.md） */
export interface AgentInfo {
  /** 定义文件绝对路径 */
  path: string
  /** global（用户级） | project（项目级） */
  scope: 'global' | 'project'
  name: string
  description: string
  /** frontmatter 的 model；空 = 继承主会话模型 */
  model: string
}

/** 内置 agent 类型及其覆盖状态（内置类型无文件定义，默认继承主会话模型） */
export interface BuiltinAgentInfo {
  /** 内置类型名（subagent_type 引用名） */
  name: string
  /** 内置默认描述 */
  description: string
  /** 生效的覆盖文件路径（项目级优先于全局）；空 = 未覆盖 */
  overridePath: string
  /** 覆盖文件作用域：'' | 'global' | 'project' */
  overrideScope: string
  /** 覆盖文件中的 model；空 = 继承主会话模型 */
  model: string
}

export interface McpServers {
  global: Record<string, unknown>
  project: Record<string, unknown>
}

/** 终端标签运行状态 */
export type TabStatus = 'working' | 'attention' | 'idle' | 'exited'

/** 一个打开的终端标签（GUI 运行时状态，不持久化） */
export interface TerminalTab {
  id: string
  projectPath: string
  /** 启动时传给 claude 的 --session-id 或 --resume 的会话 id */
  sessionId: string
  /** 实际显示的标题：有覆盖名时为覆盖名，否则等于 autoTitle */
  title: string
  /** 会话记录解析出的自动标题（未应用 titleOverrides）；覆盖名增删时据此重算 title */
  autoTitle: string
  status: TabStatus
  /** 非激活标签收到输出时标记未读 */
  unread: boolean
  /** 当前状态开始的时间戳（用于收件箱等待时长） */
  statusSince: number
  /** 最近一次等待提示或完成摘要 */
  lastNotice: string
  /** 会话实际使用的模型 ID（每回合结束时从会话记录刷新） */
  model: string
  /** 最近一回合是否使用了扩展思考 */
  thinking: boolean
  /** 启动 claude 的完整参数（TerminalView 挂载时使用） */
  args: string[]
  /** 人类可读的会话编号（用于微信通知里标识会话、回复时寻址），openTab 时单调分配 */
  wxLabel: number
}

/** 新建会话的启动选项 */
export interface LaunchOptions {
  model: string
  permissionMode: '' | 'plan' | 'acceptEdits' | 'bypassPermissions'
  extraArgs: string
}
