import { AIService } from '../../core/services';
import { logError, logInfo } from '../../utils';
import { readStocksStore, updateStock } from './stocksStore';
import { evaluateCriteria, buildVerdict, type CriteriaEvaluation } from './criteriaEval';
import type { Fundamentals } from './naverFundamentals';

/**
 * `/stocks judge <심볼>` 의 코어 — "3/4 필터" 평가.
 *
 * v2.2.211 재설계: 임계값 비교(ROE ≥ 10% 등)는 더 이상 LLM 에게 맡기지 않는다.
 * 소형 로컬 모델은 "5,800%" 파싱·다중 수치 비교에서 자주 틀리므로,
 *   - 수치 기준 7개 + 충족/미충족 판정 + 대표 키워드 3개 선택 = criteriaEval(코드, 결정론)
 *   - LLM 역할 = ① '기술력' 도메인 정성 판단(키워드 매칭이 모호할 때만)
 *               ② 평가 근거 2-3문장 서술
 * LLM 이 실패해도 판정은 항상 나온다(근거만 결정론 폴백) — judge 가 LLM 형식
 * 오류로 실패하던 경로 자체를 제거.
 *
 * `.includes("충족")` 매칭(signalClassifier)과 "[자동 평가] 충족 (A, B, C)"
 * 텍스트 계약은 기존 그대로.
 */

export interface JudgeResult {
    ok: boolean;
    /** stocks.json 에 저장된 새 "3/4 필터" 텍스트. */
    filterText?: string;
    /** 평가 근거 (사용자에게 표시). LLM 서술 또는 결정론 폴백. */
    rationale?: string;
    /** 수치 데이터 출처 ('Naver 실시간 YYYY-MM-DD' | 'stocks.json 저장값'). */
    dataSource?: string;
    error?: string;
}

const SYSTEM_PROMPT = [
    '당신은 한국·미국 주식 평가 보조 도구다. 아래 [계산 결과]는 코드가 이미 정확하게',
    '계산한 결과다 — 숫자를 재계산하거나 통과/미통과 판정을 뒤집지 말 것.',
    '요청된 출력 형식 외의 텍스트를 절대 추가하지 말 것.',
].join('\n');

function buildUserPrompt(name: string, symbol: string, ev: CriteriaEvaluation, askTech: string | null): string {
    const table = ev.results
        .map(r => `- ${r.keyword}: ${r.state === 'pass' ? '통과' : r.state === 'fail' ? '미통과' : r.state === 'llm' ? '판단 필요' : '데이터 없음'} — ${r.detail}`)
        .join('\n');
    const lines = [
        `종목: ${name} (${symbol})`,
        '',
        '[계산 결과 — 코드가 임계값을 이미 비교 완료]',
        table,
        '',
    ];
    if (askTech) {
        lines.push(
            `[질문 1] 이 종목의 최대 먹거리 '${askTech}' 가 기술 영역(AI/반도체/배터리/바이오/로봇/소프트웨어 등 기술 프리미엄이 인정되는 사업)에 해당하는가?`,
            '첫 줄에 정확히 `기술력: YES` 또는 `기술력: NO` 로만 답하라.',
            '',
        );
    }
    lines.push(
        `[질문 ${askTech ? '2' : '1'}] 위 계산 결과를 근거로 이 종목의 평가 근거를 2-3문장으로 서술하라.`,
        '구체 수치를 인용하되 표의 판정을 그대로 따르고, 새 수치·판정을 만들지 말 것.',
    );
    return lines.join('\n');
}

/** LLM 실패 시에도 판정 근거를 제공하는 결정론 폴백. */
function fallbackRationale(ev: CriteriaEvaluation): string {
    const passed = ev.results.filter(r => r.state === 'pass').map(r => r.detail);
    const failed = ev.results.filter(r => r.state === 'fail').map(r => r.detail);
    const parts: string[] = [];
    if (passed.length) parts.push(`통과: ${passed.join(' · ')}`);
    if (failed.length) parts.push(`미통과: ${failed.join(' · ')}`);
    return parts.join('\n') || '데이터 부족으로 세부 근거 없음';
}

export async function judgeStock(symbol: string, opts?: { fresh?: Fundamentals }): Promise<JudgeResult> {
    const store = readStocksStore();
    const stock = store.find(s => s.심볼 === symbol);
    if (!stock) {
        return { ok: false, error: `심볼 ${symbol} 을 stocks.json 에서 못 찾음` };
    }

    // 1) 결정론 평가 (fresh 수치가 있으면 우선 사용)
    const ev = evaluateCriteria(stock, opts?.fresh);
    const techRow = ev.results.find(r => r.keyword === '기술력');
    const needTechLlm = techRow?.state === 'llm';

    // 2) LLM — 기술력 정성 판단(필요시) + 근거 서술. 실패해도 판정은 계속.
    let techPass: boolean | undefined;
    let rationale: string | undefined;
    try {
        const ai = new AIService();
        const result = await ai.chat({
            system: SYSTEM_PROMPT,
            user: buildUserPrompt(stock.이름, symbol, ev, needTechLlm ? (stock['최대 먹거리'] || '') : null),
        });
        const content = (result.content || '').trim();
        if (!result.empty && content) {
            if (needTechLlm) {
                const m = content.match(/기술력\s*[:：]\s*(YES|NO)/i);
                if (m) techPass = m[1].toUpperCase() === 'YES';
                rationale = content.replace(/^.*기술력\s*[:：]\s*(YES|NO).*$/im, '').trim() || undefined;
            } else {
                rationale = content;
            }
        }
    } catch (e: any) {
        logError('Stocks judge LLM 보조 호출 실패 — 결정론 폴백 사용.', { symbol, error: e?.message ?? String(e) });
    }
    if (needTechLlm && techPass === undefined) {
        // LLM 무응답/형식불량 → 보수적으로 미통과 처리 (지어내지 않음)
        techPass = false;
    }
    if (!rationale) rationale = fallbackRationale(ev);

    // 3) 판정 + 대표 3개 (코드) → 저장
    const verdict = buildVerdict(ev, stock.투자성향, techPass);
    const filterText = `[자동 평가] ${verdict.text}`;
    const wrote = updateStock(symbol, { '3/4 필터': filterText });
    if (!wrote) return { ok: false, error: 'stocks.json 쓰기 실패' };

    logInfo('Stocks judge 완료 (결정론 판정).', {
        symbol, filterText, dataSource: ev.dataSource,
        passed: verdict.passed.join(','), techLlm: needTechLlm ? String(techPass) : 'n/a',
    });
    return { ok: true, filterText, rationale, dataSource: ev.dataSource };
}
