import * as fs from 'fs';

/**
 * "자동 chronicle 기록" 흐름의 *분류기* — 사용자 메시지 + assistant 답변을 보고
 * 어떤 record type (planning / discussion / decision / development / bug) 으로
 * 저장할지, 또 어떤 프로젝트 경로 / 변경 파일을 자동 캡처할지 결정.
 *
 * 모두 stateless 정규식 / fs.statSync 기반 — sidebarProvider 의 옛 private
 * 메서드를 그대로 추출.
 *
 *   - extractLocalProjectPath(text) — 메시지 본문에서 `/Volumes/...` 절대 경로 추출 + 디렉토리 검증
 *   - inferAutoChronicleRecordType(user, assistant) — 6 분기 키워드 매칭 (옵트아웃 우선)
 *   - extractChangedFilesFromText(text) — assistant 응답에서 backtick 코드/문서 파일명 추출
 */

/**
 * Antigravity workspace 절대 경로를 메시지에서 발견. 결과가 실제로 존재하는
 * 디렉토리일 때만 반환 — fs.statSync 가 throw 하면 null.
 */
export function extractLocalProjectPath(text: string): string | null {
    const match = text.match(/\/Volumes\/Data\/project\/Antigravity\/[^\s`"'<>]+/i);
    if (!match) return null;
    const candidate = match[0].replace(/[.,;:)\]]+$/, '');
    try {
        if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
            return candidate;
        }
    } catch {
        return null;
    }
    return null;
}

/**
 * 메시지 한 쌍을 6 record type 중 하나로 분류. 분류 우선순위:
 *   0) opt-out 키워드 ("기록하지마" / "do not record") → null
 *   1) topic 키워드 (프로젝트/코드/아키텍처 등) 가 *전혀* 없으면 null
 *   2) bug 키워드가 user 에 있으면 'bug'
 *   3) "수정 완료/구현 완료/jest passed" 류가 assistant 에 있으면 'development'
 *   4) "결정/채택/decision" 류 있으면 'decision'
 *   5) "계획/설계/아키텍처/roadmap" 류가 user 에 있으면 'planning'
 *   6) "개선/구현/test" 류가 combined 에 있으면 'development'
 *   7) 그 외 'discussion'
 *
 * 순서는 *덮어쓰기* — 더 구체적인 매칭이 먼저. 변경 시 회귀 위험 있으니 유지.
 */
export function inferAutoChronicleRecordType(
    userText: string,
    assistantText: string,
): 'planning' | 'discussion' | 'decision' | 'development' | 'bug' | null {
    const combined = `${userText}\n${assistantText}`;
    if (!combined.trim()) return null;
    if (/(기록하지마|저장하지마|no\s+record|do\s+not\s+record)/i.test(combined)) return null;
    if (!/(프로젝트|코드|아키텍처|설계|개선|수정|구현|테스트|검증|이슈|문제|버그|오류|끊김|결정|방향|기록|지식|review|architecture|implement|fix|bug|issue|test|decision)/i.test(combined)) {
        return null;
    }
    if (/(버그|오류|에러|이슈|문제|끊김|안\s*됨|실패|bug|error|issue|failed|failure)/i.test(userText)) {
        return 'bug';
    }
    if (/(수정 완료|개선 완료|구현 완료|패치|테스트.*통과|검증.*완료|변경.*파일|compile|jest|tsc|passed|implemented|fixed)/i.test(assistantText)) {
        return 'development';
    }
    if (/(결정|확정|채택|방향은|하기로|하지 않기로|decision|decide|accepted)/i.test(combined)) {
        return 'decision';
    }
    if (/(계획|설계|아키텍처|조사|방향|로드맵|mvp|planning|architecture|roadmap|design)/i.test(userText)) {
        return 'planning';
    }
    if (/(개선|수정|구현|테스트|검증|패킹|compile|jest|tsc|implement|fix|test|verify)/i.test(combined)) {
        return 'development';
    }
    return 'discussion';
}

/**
 * Assistant 답변의 backtick 코드/문서 파일명 추출. 최대 12개로 cap.
 * 추출 결과가 0개면 placeholder 문구 한 줄 반환 (record 의 changedFiles 가
 * 빈 배열이면 template 이 깨지는 케이스 회피).
 */
export function extractChangedFilesFromText(text: string): string[] {
    const files = new Set<string>();
    for (const match of text.matchAll(/`([^`\n]+\.(?:ts|tsx|js|jsx|json|md|css|html|py|yml|yaml))`/gi)) {
        files.add(match[1].trim());
    }
    return files.size > 0
        ? Array.from(files).slice(0, 12)
        : ['No explicit changed file list was captured automatically.'];
}
