/**
 * Skill Score + Success Pattern DB — 역량 점수와 성공 사례 축적 (설계서 12장).
 *
 * Self-Evolving OS 마스터 플랜 Phase 6 / Track 7-3 + 7-4.
 *
 * Skill Score (0~100, 업무 유형 단위 v1):
 *   최근 N건 reflection 의 (확신도 50% + 요소 충족률 30% + 비에스컬레이션율 20%).
 *   전반기/후반기 비교로 추세(↑/→/↓)를 산출 — "SEO 52→81" 류 성장 표시의 원천.
 *
 * Success Pattern DB:
 *   전 요소 충족 + 확신도 high 인 업무 turn 을 <brain>/.astra/growth/success-patterns.jsonl
 *   에 적재. v1 은 기록·집계 (향후 증분: 신규 업무 turn 에 모범 사례로 주입).
 */

import * as fs from 'fs';
import * as path from 'path';
import type { ReflectionRecord } from './reflectionStore';

export const SUCCESS_PATTERNS_REL_PATH = path.join('.astra', 'growth', 'success-patterns.jsonl');

// ─────────────────────────── Skill Score ───────────────────────────

export interface SkillScoreItem {
    taskId: string;
    taskLabel: string;
    /** 0~100. */
    score: number;
    /** 전반기 대비 후반기 — 'up' | 'flat' | 'down'. 표본 4건 미만이면 'flat'. */
    trend: 'up' | 'flat' | 'down';
    /** 전반기/후반기 점수 (추세 근거). */
    firstHalf: number;
    secondHalf: number;
    sampleCount: number;
}

function scoreOf(rs: ReflectionRecord[]): number {
    if (rs.length === 0) return 0;
    const avgConf = rs.reduce((s, r) => s + (r.confidenceScore || 0), 0) / rs.length;
    const coverOk = rs.filter((r) => (r.missing || []).length === 0).length / rs.length;
    const noEsc = rs.filter((r) => !r.escalated).length / rs.length;
    return Math.round(avgConf * 0.5 + coverOk * 100 * 0.3 + noEsc * 100 * 0.2);
}

export function computeSkillScores(records: ReflectionRecord[]): SkillScoreItem[] {
    const byTask = new Map<string, ReflectionRecord[]>();
    for (const r of records) {
        if (!r.taskId) continue;
        const arr = byTask.get(r.taskId) || [];
        arr.push(r);
        byTask.set(r.taskId, arr);
    }
    const items: SkillScoreItem[] = [];
    for (const [taskId, rs] of byTask) {
        // ts 순 정렬 후 전/후반 비교.
        const sorted = rs.slice().sort((a, b) => a.ts.localeCompare(b.ts));
        const mid = Math.floor(sorted.length / 2);
        const firstHalf = scoreOf(sorted.slice(0, mid));
        const secondHalf = scoreOf(sorted.slice(mid));
        let trend: SkillScoreItem['trend'] = 'flat';
        if (sorted.length >= 4) {
            if (secondHalf - firstHalf >= 5) trend = 'up';
            else if (firstHalf - secondHalf >= 5) trend = 'down';
        }
        items.push({
            taskId,
            taskLabel: sorted[0].taskLabel || taskId,
            score: scoreOf(sorted),
            trend,
            firstHalf,
            secondHalf,
            sampleCount: sorted.length,
        });
    }
    return items.sort((a, b) => b.score - a.score);
}

export function formatSkillScoresMarkdown(items: SkillScoreItem[]): string {
    const lines: string[] = [];
    lines.push('## Skill Score (역량 점수)');
    lines.push('');
    lines.push('확신도 50% + 요소 충족률 30% + 비에스컬레이션율 20%. 추세는 전/후반기 비교 (표본 4건+).');
    lines.push('');
    if (items.length === 0) {
        lines.push('- 데이터 없음');
        return lines.join('\n');
    }
    const arrow = { up: '📈 상승', flat: '→ 유지', down: '📉 하락' } as const;
    lines.push('| 업무 | Score | 추세 | 전반기→후반기 | 표본 |');
    lines.push('|---|---|---|---|---|');
    for (const it of items) {
        lines.push(`| ${it.taskLabel} | **${it.score}** | ${arrow[it.trend]} | ${it.firstHalf}→${it.secondHalf} | ${it.sampleCount} |`);
    }
    return lines.join('\n');
}

// ─────────────────────── Success Pattern DB ───────────────────────

export interface SuccessPattern {
    ts: string;
    taskId: string;
    taskLabel: string;
    confidenceScore: number;
    promptPreview: string;
    usedSources: string[];
}

/** 성공 판정 — 전 요소 충족 + 확신도 high(90+). */
export function isSuccessTurn(record: ReflectionRecord): boolean {
    return !!record.taskId
        && (record.missing || []).length === 0
        && record.confidenceScore >= 90;
}

export function appendSuccessPattern(brainPath: string, record: ReflectionRecord): boolean {
    try {
        if (!isSuccessTurn(record)) return false;
        const file = path.join(brainPath, SUCCESS_PATTERNS_REL_PATH);
        fs.mkdirSync(path.dirname(file), { recursive: true });
        const pattern: SuccessPattern = {
            ts: record.ts,
            taskId: record.taskId!,
            taskLabel: record.taskLabel || record.taskId!,
            confidenceScore: record.confidenceScore,
            promptPreview: record.promptPreview,
            usedSources: record.usedSources || [],
        };
        fs.appendFileSync(file, JSON.stringify(pattern) + '\n', 'utf8');
        return true;
    } catch {
        return false;
    }
}

export function loadSuccessPatterns(brainPath: string, limit?: number): SuccessPattern[] {
    try {
        const file = path.join(brainPath, SUCCESS_PATTERNS_REL_PATH);
        if (!fs.existsSync(file)) return [];
        const lines = fs.readFileSync(file, 'utf8').split('\n').filter((l) => l.trim());
        const out: SuccessPattern[] = [];
        for (const line of lines) {
            try {
                const obj = JSON.parse(line);
                if (obj && typeof obj.ts === 'string' && typeof obj.taskId === 'string') out.push(obj);
            } catch { /* skip */ }
        }
        return limit && limit > 0 ? out.slice(-limit) : out;
    } catch {
        return [];
    }
}

export function formatSuccessPatternsMarkdown(patterns: SuccessPattern[]): string {
    const lines: string[] = [];
    lines.push('## Success Patterns (성공 사례)');
    lines.push('');
    if (patterns.length === 0) {
        lines.push('- 아직 없음 — 전 요소 충족 + 확신도 90+ 인 업무가 자동 축적됩니다.');
        return lines.join('\n');
    }
    const byTask = new Map<string, number>();
    for (const p of patterns) byTask.set(p.taskLabel, (byTask.get(p.taskLabel) || 0) + 1);
    lines.push(`총 ${patterns.length}건 — ${Array.from(byTask.entries()).map(([l, c]) => `${l} ${c}건`).join(' · ')}`);
    lines.push('');
    for (const p of patterns.slice(-5).reverse()) {
        lines.push(`- [${p.ts.slice(0, 10)}] ${p.taskLabel} (확신도 ${p.confidenceScore}) — "${p.promptPreview.slice(0, 60)}"`);
    }
    return lines.join('\n');
}
