import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import path from 'node:path'

const scriptDir = path.dirname(fileURLToPath(import.meta.url))
const mockDataPath = path.resolve(scriptDir, '../src/mock/data.ts')
const mockAdapterPath = path.resolve(scriptDir, '../src/mock/adapter.ts')
const modelPath = path.resolve(scriptDir, '../src/views/system/training-log/trainingLogModel.ts')
const [mockData, mockAdapter, modelSource] = await Promise.all([
  readFile(mockDataPath, 'utf8'),
  readFile(mockAdapterPath, 'utf8'),
  readFile(modelPath, 'utf8'),
])

function objectFromMarker(source, marker) {
  const markerIndex = source.indexOf(marker)
  assert.notEqual(markerIndex, -1, `未找到 Mock 数据标记：${marker}`)
  const openBrace = source.lastIndexOf('{', markerIndex)
  assert.notEqual(openBrace, -1, `Mock 数据缺少对象起点：${marker}`)

  let depth = 0
  for (let index = openBrace; index < source.length; index += 1) {
    if (source[index] === '{') depth += 1
    if (source[index] === '}') depth -= 1
    if (depth === 0) return source.slice(openBrace, index + 1)
  }

  assert.fail(`Mock 数据缺少对象终点：${marker}`)
}

const taskNames = [
  'finance-sft-001',
  'legal-sft-002',
  'medical-cpt-001',
  'service-dpo-001',
  'finance-sft-002',
  'general-sft-001',
]
const commonTrainingFields = [
  'output_model_name',
  'batch_size',
  'learning_rate',
  'n_epochs',
  'save_steps',
  'lr_scheduler_type',
  'max_length',
  'warmup_ratio',
  'weight_decay',
]

for (const taskName of taskNames) {
  const task = objectFromMarker(mockData, `name: '${taskName}'`)
  for (const field of commonTrainingFields) {
    assert.match(task, new RegExp(`\\b${field}\\s*:`), `${taskName} 缺少训练参数：${field}`)
  }

  if (/train_method:\s*'lora'/.test(task)) {
    for (const field of ['lora_rank', 'lora_alpha', 'lora_dropout']) {
      assert.match(task, new RegExp(`\\b${field}\\s*:`), `${taskName} 缺少 LoRA 参数：${field}`)
    }
  }
}

const medicalTask = objectFromMarker(mockData, "name: 'medical-cpt-001'")
assert.match(medicalTask, /\bprocess_id\s*:/, '运行中的医疗训练任务缺少进程 ID')
assert.match(mockData, /medical-cpt-001_pid28741\.log/, '医疗训练任务缺少 PID 对应的日志文件')
assert.match(mockData, /export const mockTrainingLogContents/, '训练日志没有按文件提供独立 Mock 内容')
assert.match(mockData, /Num examples\s*=\s*9,800/, '医疗训练日志缺少样本规模信息')
assert.match(mockData, /Total optimization steps\s*=\s*921/, '医疗训练日志缺少真实训练步数信息')
assert.match(mockData, /\\'epoch\\':\s*1\.92/, '医疗训练日志的 Epoch 未与 64% 进度对齐')
assert.match(mockData, /\\'loss\\':\s*1\.146/, '医疗训练日志缺少当前 Loss 指标')
assert.match(mockAdapter, /const file = String\(params\.file/, '训练日志接口没有读取请求中的日志文件名')
assert.match(mockAdapter, /mockTrainingLogContents\[file\]/, '训练日志接口没有按请求文件返回对应内容')
assert.match(modelSource, /epoch:\s*number\[\]/, '训练指标模型没有保留逐步 Epoch')

console.log('训练日志 Mock 数据回归检查通过')
