/**
 * TeamOps Communication — /draft · /feedback (외부 출력·기록).
 *
 * v2.2.199 에서 slashRouter.ts 에서 분리. (원래는 v2.2.200 예정이었으나 coordination
 * 추출 시 register 라인이 인접해 묶여 함께 진행.)
 */

import * as fs from 'fs';
import * as vscode from 'vscode';
import { registerSlashCommand, chunk } from '../../datacollect/slashRouter';
import { callLmSynthesis } from '../../datacollect/llm';
import {
    appendFeedback, readFeedback, getFeedbackFilePath, countFeedback,
    type FeedbackEntry,
} from '../../feedback/feedbackStore';

// ─── /draft — 외부 커뮤니케이션 초안 ─────────────────────────────────────

const DRAFT_TYPES: Record<string, { label: string; systemPrompt: string }> = {
    email: {
        label: '이메일',
        systemPrompt: '한국어 비즈니스 이메일 초안. 격식 있되 과도하게 딱딱하지 않게. 인사 / 본문(목적·요청·맥락) / 맺음말 구조. 100~300자.',
    },
    slack: {
        label: '슬랙/메신저 메시지',
        systemPrompt: '슬랙·메신저용 짧고 명확한 한국어 메시지. 캐주얼하지만 프로페셔널. 50~150자 내. 필요하면 불릿 사용.',
    },
    blog: {
        label: '블로그 포스트',
        systemPrompt: '블로그 포스트 초안 한국어. 후크가 있는 도입부 + 본문 3~5개 섹션 + 결론. 800~2000자. 마크다운 헤더(##) 사용.',
    },
    newsletter: {
        label: '뉴스레터',
        systemPrompt: '뉴스레터용 한국어. 친근하면서 정보성. 헤드라인 + 본문 + 다음 액션 권유. 300~600자.',
    },
    'investor-update': {
        label: '투자자 월간 업데이트',
        systemPrompt: '투자자/이해관계자용 월간 업데이트 한국어. 구조: ① 핵심 지표 ② 이번 달 성과 ③ 과제·이슈 ④ 다음 우선순위 ⑤ ask (필요한 도움). 격식, 정량 지표 우선.',
    },
    proposal: {
        label: '비즈니스 제안서',
        systemPrompt: '비즈니스 제안서 초안 한국어. 구조: 배경 / 제안 내용 / 기대 효과 / 일정 / (가능하면) 비용. 격식, 명확.',
    },
};

async function runDraft(arg: string, view: any): Promise<boolean> {
    const tokens = arg.trim().split(/\s+/);
    if (!arg.trim() || tokens.length < 2) {
        const typeList = Object.entries(DRAFT_TYPES).map(([k, v]) => `  \`${k}\` — ${v.label}`).join('\n');
        chunk(view, [
            '\n📋 **/draft [유형] [요청] — 외부 커뮤니케이션 초안**',
            '',
            '사용법: `/draft <유형> <요청 내용>`',
            '',
            '유형 목록:',
            typeList,
            '',
            '예시:',
            '  `/draft email 김 대표님께 미팅 일정 조율 요청, 다음 주 가능 시간 3개 제안`',
            '  `/draft slack 디자이너에게 메인 시안 1차 컨펌 요청, 금요일까지 회신 부탁`',
            '  `/draft blog v2.2 릴리즈 노트 — Tasks 통합 및 4인 팀 운영 기능 소개`',
            '  `/draft investor-update 5월 월간 — MAU 30% 성장, 결제 흐름 개선 완료, 다음 달 신규 출시`',
            '',
            '※ Settings 의 `g1nation.teamVoiceGuide` 에 팀 보이스 가이드(말투/금기어/자주 쓰는 표현)를 저장하면 모든 초안에 자동 반영.',
            '',
        ].join('\n'));
        return true;
    }

    const typeKey = tokens[0].toLowerCase();
    const typeDef = DRAFT_TYPES[typeKey];
    if (!typeDef) {
        chunk(view, `\n❌ 알 수 없는 유형: \`${typeKey}\`. 사용 가능: ${Object.keys(DRAFT_TYPES).join(' · ')}\n`);
        return true;
    }
    const request = tokens.slice(1).join(' ').trim();
    if (!request) { chunk(view, '\n❌ 요청 내용 없음.\n'); return true; }

    const voiceGuide = (vscode.workspace.getConfiguration('g1nation').get<string>('teamVoiceGuide', '') || '').trim();
    chunk(view, `\n📝 **${typeDef.label} 초안 작성 중**\n  · 요청: ${request}\n  · ${voiceGuide ? '팀 보이스 가이드 적용 (' + voiceGuide.length + '자)' : '팀 보이스 가이드 없음 (g1nation.teamVoiceGuide 설정 시 자동 반영)'}\n`);

    const systemPrompt = [
        typeDef.systemPrompt,
        '',
        voiceGuide ? `[팀 보이스 가이드 — 반드시 준수]\n${voiceGuide}` : '',
        '',
        '출력 형식: 초안 본문만. "네, 알겠습니다" 같은 인사·메타 설명 금지. 사용자가 그대로 복사해 보낼 수 있는 형태.',
    ].filter(Boolean).join('\n');

    try {
        const draft = await callLmSynthesis(request, systemPrompt);
        if (!draft || !draft.trim()) { chunk(view, '\n❌ 초안 생성 실패 (LLM 빈 응답).\n'); return true; }
        chunk(view, `\n---\n${draft.trim()}\n---\n`);
    } catch (e: any) {
        chunk(view, `\n❌ 초안 생성 실패: ${e?.message ?? String(e)}\n`);
    }
    return true;
}

// ─── /feedback — 고객 피드백 누적 + 패턴 분석 ───────────────────────────

const FEEDBACK_CATEGORIZE_PROMPT = [
    '당신은 고객 피드백 분류기.',
    '',
    '[입력] 사용자가 제공하는 고객 피드백 텍스트 한 건.',
    '',
    '[출력 형식 — 정확히 이 JSON 한 줄, 다른 텍스트/설명 절대 금지]',
    '{"categories":["..."],"sentiment":"positive|neutral|negative"}',
    '',
    '[규칙]',
    '- categories: 1~3개. 짧은 한국어 단어. 일관된 분류 (예: UX, 결제, 성능, 안정성, 가격, 신뢰, 기능 요청, 버그, 사용성, 디자인, 고객지원). 명확하지 않으면 "기타".',
    '- sentiment: 긍정 호평 = positive, 단순 질문/중립 = neutral, 불만/버그/요청 = negative.',
    '- JSON 외 어떤 문자도 출력하지 마시오. 마크다운 코드블록도 금지.',
].join('\n');

const FEEDBACK_SUMMARY_PROMPT = [
    '당신은 고객 피드백 분석가. 사용자가 제공한 누적 피드백 데이터(JSON Lines)를 보고',
    '*패턴 분석 리포트* 를 한국어 마크다운으로 작성한다. 외부 정보 추측 금지 — 주어진 데이터에서만.',
    '',
    '[출력 형식 — 정확히 이 구조]',
    '',
    '## 카테고리 분포',
    '- 카테고리명 (N건, X%): 핵심 패턴 한 줄',
    '- ...',
    '',
    '## 감정 분포',
    '- 부정: N건 (X%)',
    '- 중립: N건 (X%)',
    '- 긍정: N건 (X%)',
    '',
    '## 반복 패턴 Top 3',
    '구체적 인용 1-2개씩 포함. "여러 명이 X 에 대해 Y 하다고 언급" 형태.',
    '1. ...',
    '2. ...',
    '3. ...',
    '',
    '## 추천 액션 (대표 의사결정 참고용)',
    '데이터에서 *명확하게* 보이는 신호만. 단정적 단어("반드시" 등) 금지, "검토 권장" 톤.',
    '- ...',
].join('\n');

async function feedbackSave(text: string, view: any): Promise<void> {
    if (!text.trim()) { chunk(view, '\n❌ 피드백 텍스트가 비어 있습니다.\n'); return; }

    const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    const initialEntry: FeedbackEntry = { id, timestamp: new Date().toISOString(), text: text.trim() };
    const saveResult = appendFeedback(initialEntry);
    if (!saveResult.ok) { chunk(view, `\n❌ 저장 실패: ${saveResult.error}\n`); return; }
    chunk(view, `\n📥 **피드백 저장됨** (id: \`${id.slice(0, 13)}\`)\n  · 누적 ${countFeedback()}건\n`);

    chunk(view, '\n🤖 카테고리 자동 분류 중...\n');
    try {
        const llmOut = await callLmSynthesis(text.trim(), FEEDBACK_CATEGORIZE_PROMPT);
        const jsonMatch = llmOut.match(/\{[\s\S]*\}/);
        if (!jsonMatch) { chunk(view, '  ⚠️ 분류 실패 (LLM 응답에 JSON 없음). 원본은 저장됨, 수동으로 분류 추가 가능.\n'); return; }
        const parsed = JSON.parse(jsonMatch[0]);
        const categories: string[] = Array.isArray(parsed.categories) ? parsed.categories.map(String).slice(0, 3) : [];
        const sentiment = ['positive', 'neutral', 'negative'].includes(parsed.sentiment) ? parsed.sentiment : undefined;
        const enriched: FeedbackEntry = { ...initialEntry, categories, sentiment };
        const all = readFeedback().map((e) => (e.id === id ? enriched : e));
        const filePath = getFeedbackFilePath();
        if (filePath) fs.writeFileSync(filePath, all.map((e) => JSON.stringify(e)).join('\n') + '\n', 'utf-8');
        chunk(view, `  · 카테고리: ${categories.length > 0 ? categories.join(', ') : '(없음)'}\n  · 감정: ${sentiment ?? '(미분류)'}\n`);
    } catch (e: any) {
        chunk(view, `  ⚠️ 분류 실패: ${e?.message || String(e)} (원본은 저장됨)\n`);
    }
}

function feedbackList(filterCategory: string | undefined, view: any): void {
    const all = readFeedback();
    const filtered = filterCategory
        ? all.filter((e) => (e.categories || []).some((c) => c === filterCategory || c.toLowerCase() === filterCategory.toLowerCase()))
        : all;
    if (filtered.length === 0) {
        chunk(view, filterCategory ? `\nℹ️ 카테고리 "${filterCategory}" 매치 0건.\n` : '\nℹ️ 누적 피드백 없음. `/feedback <텍스트>` 로 첫 항목 추가.\n');
        return;
    }
    chunk(view, `\n📋 **피드백 목록 (${filtered.length}건${filterCategory ? `, 카테고리 "${filterCategory}"` : ''})**\n\n`);
    const sorted = filtered.slice().sort((a, b) => (b.timestamp || '').localeCompare(a.timestamp || '')).slice(0, 20);
    for (const e of sorted) {
        const date = (e.timestamp || '').slice(0, 10);
        const cats = (e.categories || []).join(', ') || '미분류';
        const sentEmoji = e.sentiment === 'positive' ? '🟢' : e.sentiment === 'negative' ? '🔴' : e.sentiment === 'neutral' ? '⚪' : '❓';
        chunk(view, `- ${sentEmoji} \`${date}\` [${cats}] ${e.text.slice(0, 120)}${e.text.length > 120 ? '…' : ''}\n`);
    }
    if (filtered.length > 20) chunk(view, `\n_…+${filtered.length - 20}건 더 (필터링하거나 \`/feedback path\` 로 직접 파일 열기)_\n`);
}

async function feedbackSummary(view: any): Promise<void> {
    const all = readFeedback();
    if (all.length < 3) {
        chunk(view, `\nℹ️ 누적 ${all.length}건 — 패턴 분석엔 최소 3건 필요. \`/feedback <텍스트>\` 로 더 모아 주세요.\n`);
        return;
    }
    chunk(view, `\n📊 **패턴 분석 시작** (누적 ${all.length}건)\n  · LLM 호출 중...\n`);
    const summaryInput = all.map((e) => JSON.stringify({
        timestamp: (e.timestamp || '').slice(0, 10),
        categories: e.categories || [],
        sentiment: e.sentiment || 'unknown',
        text: e.text.slice(0, 300),
    })).join('\n');
    try {
        const report = await callLmSynthesis(`[누적 피드백 ${all.length}건]\n\n${summaryInput}`, FEEDBACK_SUMMARY_PROMPT);
        if (!report || !report.trim()) { chunk(view, '\n❌ LLM 빈 응답.\n'); return; }
        chunk(view, `\n${report.trim()}\n`);
    } catch (e: any) {
        chunk(view, `\n❌ 분석 실패: ${e?.message || String(e)}\n`);
    }
}

function feedbackPath(view: any): void {
    const p = getFeedbackFilePath();
    if (!p) { chunk(view, '\n⚠️ 워크스페이스 폴더 없음 — 저장 위치 결정 불가.\n'); return; }
    chunk(view, `\n📂 \`${p}\`\n  · 누적 ${countFeedback()}건 (.jsonl 형식, 한 줄=한 항목)\n  · 사람이 직접 편집 가능 — 카테고리 수정·삭제 등.\n`);
}

async function runFeedback(arg: string, view: any): Promise<boolean> {
    const trimmed = arg.trim();
    if (!trimmed) {
        chunk(view, [
            '\n📋 **/feedback — 고객 피드백 누적 + 패턴 분석**',
            '',
            '사용법:',
            '  `/feedback <텍스트>`           — 피드백 저장 (LLM 자동 카테고리 분류)',
            '  `/feedback list [카테고리]`    — 누적 목록 (최신순, 최대 20건)',
            '  `/feedback summary`            — 누적 데이터 패턴 분석 리포트 (LLM)',
            '  `/feedback path`               — 저장 파일 경로 표시',
            '',
            '예시:',
            '  `/feedback 결제 흐름이 너무 복잡해서 중간에 포기했어요 - 김XX`',
            '  `/feedback list 결제`',
            '  `/feedback summary`  (3건+ 누적 시)',
            '',
            '저장 위치: `<workspace>/.astra/customer-feedback.jsonl` — 로컬 only, 외부 전송 없음.',
            '',
        ].join('\n'));
        return true;
    }

    const firstSpace = trimmed.search(/\s/);
    const head = (firstSpace < 0 ? trimmed : trimmed.slice(0, firstSpace)).toLowerCase();
    const rest = firstSpace < 0 ? '' : trimmed.slice(firstSpace + 1).trim();

    switch (head) {
        case 'list': feedbackList(rest || undefined, view); return true;
        case 'summary': case 'analyze': case 'report': await feedbackSummary(view); return true;
        case 'path': feedbackPath(view); return true;
        default: await feedbackSave(trimmed, view); return true;
    }
}

// ─── 등록 ─────────────────────────────────────────────────────────────────

registerSlashCommand({ name: '/draft', description: '외부 커뮤니케이션 초안 — email/slack/blog/newsletter/investor-update/proposal', handler: runDraft });
registerSlashCommand({ name: '/feedback', description: '고객 피드백 누적 + 자동 카테고리 분류 + 패턴 분석 (로컬 .jsonl)', handler: runFeedback });
