// recordAnalytics — 零件執行結果回寫（POST /analytics/record 的實作）
// SDD: system-dev/docs/3-specs/arcrun-core-mvp/design.md「執行統計設計」
//
// 真相源＝ANALYTICS_KV 計數器（key = stats:{hash_id}:{version}，見 src/types.ts 註記）：
//   { total_runs, success_runs, total_ms }
// 讀取端（queryComponents / GET /components/*）讀的是 comp: 記錄上的
// success_rate / avg_duration_ms / call_count 欄位——所以每次記錄後把衍生值
// 回填 comp: 記錄（唯一寫入者是本函式，衍生值不是第二個真相源）。
//
// 尺度註記：design.md:499 寫 success_rate = success_runs / total_runs * 100（百分比顯示）。
// 本 repo comp: 記錄的 success_rate 既有尺度是 0..1（預設 1，computeScore 直接相乘），
// 為不破壞既有讀取端與未測零件的預設值，落庫維持 0..1；*100 只是等價的顯示換算。
//
// 誠實限制：CF KV 無 CAS/原子遞增，read-modify-write 併發下偶有丟計數；
// 統計用途可接受（design 的「樂觀鎖」在 KV 上做不到，不假裝做到了）。

import type { Bindings } from '../types';
import { computeScore } from './queryComponents';

export interface AnalyticsRecordInput {
  canonical_id: string;        // 也接受 cmp_xxxxxxxx hash_id
  version?: string;            // 不給 → 記到查詢會回的最優版本（getComponent 同判準）
  success: boolean;
  duration_ms: number;
}

export interface AnalyticsRecordResult {
  ok: boolean;
  error?: string;
  canonical_id?: string;
  version?: string;
  total_runs?: number;
  success_runs?: number;
  success_rate?: number;       // 0..1，與 comp: 記錄同尺度
  avg_duration_ms?: number;
}

interface StatsCounters {
  total_runs: number;
  success_runs: number;
  total_ms: number;
}

export async function recordAnalytics(
  input: AnalyticsRecordInput,
  env: Bindings,
): Promise<AnalyticsRecordResult> {
  // 1. 解析 hash_id（與 queryComponents.resolveHashId 同規則）
  const hashId = input.canonical_id.startsWith('cmp_')
    ? input.canonical_id
    : await env.SUBMISSIONS_KV.get(`idx:${input.canonical_id}`);
  if (!hashId) {
    return { ok: false, error: `零件 ${input.canonical_id} 不在索引` };
  }

  // 2. 找目標版本記錄：指定 version 就用它；沒指定 → 最優版本（與 getComponent 同判準：score 最高）
  const list = await env.SUBMISSIONS_KV.list({ prefix: `comp:${hashId}:` });
  let targetKey: string | null = null;
  let targetRecord: Record<string, unknown> | null = null;
  let bestScore = -Infinity;

  for (const key of list.keys) {
    const raw = await env.SUBMISSIONS_KV.get(key.name);
    if (!raw) continue;
    let v: Record<string, unknown>;
    try { v = JSON.parse(raw); } catch { continue; }
    if (v.status === 'tombstone') continue;

    if (input.version) {
      if (String(v.version) === input.version) {
        targetKey = key.name;
        targetRecord = v;
        break;
      }
      continue;
    }
    const score = computeScore(v);
    if (score > bestScore) {
      bestScore = score;
      targetKey = key.name;
      targetRecord = v;
    }
  }

  if (!targetKey || !targetRecord) {
    return { ok: false, error: `零件 ${input.canonical_id} 無可用版本記錄` };
  }

  const version = String(targetRecord.version ?? 'v1');
  const canonicalId = String(targetRecord.canonical_id ?? input.canonical_id);

  // 3. 更新計數器（真相源，ANALYTICS_KV stats:{hash_id}:{version}）
  const statsKey = `stats:${hashId}:${version}`;
  let counters: StatsCounters = { total_runs: 0, success_runs: 0, total_ms: 0 };
  const rawStats = await env.ANALYTICS_KV.get(statsKey);
  if (rawStats) {
    try {
      const parsed = JSON.parse(rawStats) as Partial<StatsCounters>;
      counters = {
        total_runs: Number(parsed.total_runs) || 0,
        success_runs: Number(parsed.success_runs) || 0,
        total_ms: Number(parsed.total_ms) || 0,
      };
    } catch { /* 損毀計數器 → 重新起算 */ }
  }
  counters.total_runs += 1;
  counters.success_runs += input.success ? 1 : 0;
  counters.total_ms += Math.max(0, Number(input.duration_ms) || 0);
  await env.ANALYTICS_KV.put(statsKey, JSON.stringify(counters));

  // 4. 衍生值回填 comp: 記錄（讀取端讀的地方）
  const successRate = counters.success_runs / counters.total_runs;
  const avgDurationMs = Math.round(counters.total_ms / counters.total_runs);
  targetRecord.success_rate = successRate;
  targetRecord.avg_duration_ms = avgDurationMs;
  targetRecord.call_count = counters.total_runs;
  await env.SUBMISSIONS_KV.put(targetKey, JSON.stringify(targetRecord));

  return {
    ok: true,
    canonical_id: canonicalId,
    version,
    total_runs: counters.total_runs,
    success_runs: counters.success_runs,
    success_rate: successRate,
    avg_duration_ms: avgDurationMs,
  };
}
