import type { BrainProfile } from '../../config';

/**
 * Status broadcast 메시지의 *payload 빌더* 모음. webview send 호출은 여전히
 * sidebarProvider 가 담당 — 이 모듈은 stateless 데이터 변환만 책임.
 *
 *   - buildBrainStatusPayload(profile, fileCount) — `brainStatus` 메시지
 *   - buildBrainProfilesPayload(profiles, activeId) — `brainProfiles` 메시지
 *   - buildReadyStatusPayload(deps) — `readyStatus` 메시지 (한 줄 readiness snapshot)
 *
 * 옛 코드: sidebarProvider 의 `_sendBrainStatus`, `_sendBrainProfiles`,
 * `_postBrainProfiles`, `_sendReadyStatus` 가 각자 payload 를 inline 으로 만들었음.
 * 단위 테스트 노출 + payload shape 변경 시 한 곳만 수정 + send/build 책임 분리.
 *
 * Why ready status 는 deps struct 패턴: provider 가 비싼 read (loadedModels probe,
 * findBrainFiles, scope 해상, etc.) 를 *수행* 한 뒤 결과만 넘기는 게 깔끔. 빌더가
 * 직접 I/O 해버리면 mock 어려움 + 캐시 무력화.
 */

/** Sidebar 의 brain status 칩에 표시되는 정보 (count + path + name + 메타). */
export function buildBrainStatusPayload(
    profile: BrainProfile,
    fileCount: number,
): { type: 'brainStatus'; value: { count: number; path: string; name: string; description: string; repo: string } } {
    return {
        type: 'brainStatus',
        value: {
            count: fileCount,
            path: profile.localBrainPath,
            name: profile.name,
            description: profile.description || '',
            repo: profile.secondBrainRepo || '',
        },
    };
}

/**
 * Brain 선택 dropdown 의 모델. config raw shape (any[]) 도 받아 동일 출력 shape
 * 으로 정규화 — 새로 추가/편집 직후 cfg.update() async 가 캐시에 반영되기 전에
 * 호출되는 케이스 대응.
 */
export function buildBrainProfilesPayload(
    profiles: ReadonlyArray<BrainProfile> | any[],
    activeBrainId: string,
): { type: 'brainProfiles'; value: { activeBrainId: string; profiles: Array<{ id: string; name: string; path: string; description: string; repo: string }> } } {
    return {
        type: 'brainProfiles',
        value: {
            activeBrainId,
            profiles: (profiles as any[]).map((p: any) => ({
                id: p.id || '',
                name: p.name || '',
                path: p.localBrainPath || p.path || '',
                description: p.description || '',
                repo: p.secondBrainRepo || p.repo || '',
            })),
        },
    };
}

/**
 * Sidebar 한 줄 readiness 칩 ("engine online? model loaded? brain N files …").
 * Provider 가 비싼 lookup (loadedModels, findBrainFiles, scope 해상) 을 미리 수행
 * 한 뒤 결과만 deps 로 넘긴다.
 */
export interface ReadyStatusDeps {
    engineKind: 'lmstudio' | 'ollama';
    engineOnline: boolean | null;
    modelName: string;
    /** LM Studio 에서만 의미 — null = 미확인/probe 실패 */
    modelLoaded: boolean | null;
    modelParamB: number | null;
    brainName: string;
    brainFiles: number;
    agentName: string | null;
    agentScopeFolders: number;
    agentMapped: boolean;
    memoryEnabled: boolean;
    multiAgentEnabled: boolean;
    contextLength: number;
    /** 작은 모델 cap 적용 후 *실효* context. providers always 같지 않을 수 있음. */
    effectiveContextLength: number;
    cappedForSmallModel: boolean;
    lmStudioError: string | null;
    /** HealthCheckMonitor 의 마지막 환경 경고 (Bridge·볼륨·자격증명·버전 등). 없으면 []. */
    healthWarnings: string[];
}

export function buildReadyStatusPayload(d: ReadyStatusDeps) {
    return {
        type: 'readyStatus' as const,
        value: {
            engine: {
                kind: d.engineKind,
                label: d.engineKind === 'lmstudio' ? 'LM Studio' : 'Ollama',
                online: d.engineOnline,
            },
            model: { name: d.modelName, loaded: d.modelLoaded, paramB: d.modelParamB },
            brain: { name: d.brainName, files: d.brainFiles },
            agent: { name: d.agentName, scopeFolders: d.agentScopeFolders, mapped: d.agentMapped },
            memory: d.memoryEnabled,
            multiAgent: d.multiAgentEnabled,
            contextLength: d.effectiveContextLength,
            nominalContextLength: d.contextLength,
            cappedForSmallModel: d.cappedForSmallModel,
            lmStudioError: d.lmStudioError,
            healthWarnings: d.healthWarnings,
        },
    };
}
