/**
 * 文章朗读契约（对齐后端 spec §6）。
 *
 * 班级两个 DTO 的可空字段是 required-nullable 而非 optional：后端
 * _collect_class_rows 对每个学生都发全部键，not_started 行发 null。
 */
export type ArticlePracticeMode = 'time' | 'unlimited'
/**
 * `abandoned` 是「重新开始」的标记（后端 spec §4.2）。「哪个 session」类查询一律排除它，
 * 所以 resume 探针与 get-or-create 都不会返回它 —— 但 `GET /report` 原样回 `session.status`，
 * 拿着旧 sessionId 直接查就会拿到，契约里必须写全三个值。
 */
export type ArticleSessionStatus = 'reading' | 'completed' | 'abandoned'
export type ArticleParagraphStatus = 'pending' | 'generating' | 'completed' | 'failed'
export type ArticleOverallStatus = 'generating' | 'completed' | 'failed' | null
export type ArticleWordStatus = 'good' | 'warn' | 'bad' | 'misread' | 'omission' | 'insertion'

export interface ArticleReadingConfig {
  type: 'article'
  grade: string
  title: string
  content: string
  practice: { mode: ArticlePracticeMode; duration: number }
  evaluation: { showReport: boolean }
}

export interface ArticleReadingTask {
  id: string
  taskType: 'article-reading'
  titleZh: string
  titleEn: string
  subtitle: string
  difficulty: number
  count: 1
  unit: '篇'
  durationMinutes: number
  content: string
}

export interface ArticleScoreDimensions {
  accuracy: number
  fluency: number
  completeness: number
  prosody: number
}

export interface ArticleWordResult {
  word: string
  status: ArticleWordStatus
  accuracy: number | null
}

export interface ArticleParagraphResult {
  idx: number
  text: string
  status: ArticleParagraphStatus
  audioUrl: string | null
  overallScore: number | null
  dims: ArticleScoreDimensions | null
  /** 段内扁平词级，按对齐顺序（spec §6）。句层已在后端 c62d35a 删除，别再加回来。 */
  words: ArticleWordResult[]
}

export interface ArticleOverallResult {
  aiComment: string
  highlights: string[]
  suggestions: string[]
  overallScore: number
  dims: ArticleScoreDimensions
}

export interface ArticleReadingReport {
  sessionId: string
  title: string
  status: ArticleSessionStatus
  totalDurationSeconds: number | null
  /**
   * 绝对截止时刻（ISO8601，后端 spec §4.4）；null = 不限时。
   * **只用来显示计时、以及决定本地时钟什么时候去问一次后端** —— 到了没由后端说了算。
   */
  expiresAt: string | null
  paragraphs: ArticleParagraphResult[]
  overall: ArticleOverallResult | null
  overallStatus: ArticleOverallStatus
}

export interface ArticleStreamAck {
  type: 'ack'
  status: 'generating'
  attempt: number
  truncated: boolean
}

export interface ArticleClassUser {
  userId: string
  name: string
}

export interface ArticleClassSessionSummary extends ArticleClassUser {
  status: 'completed' | 'reading' | 'not_started'
  sessionId: string | null
  overallScore: number | null
  dims: ArticleScoreDimensions | null
  completedAt: string | null
}

export interface ArticleClassSummaryResponse {
  summary: string
  generatedAt: string
  fromCache: boolean
  llmStatus: 'ok' | 'fallback'
}
