import type { CompanyResumeState, CompanyState } from '../../features/company';
import {
    listActiveAgentsByCategory,
    summarizeForChip,
    PIPELINE_TEMPLATES,
    ROLE_CATEGORY_LABELS,
    ROLE_CATEGORY_ORDER,
    COMPANY_AGENTS,
    COMPANY_AGENT_ORDER,
    resolveAgent,
} from '../../features/company';

/**
 * Company (1인 기업) 모드 webview status payload 빌더. webview send 호출은
 * 여전히 sidebarProvider 가 담당 — 이 모듈은 stateless 데이터 변환만.
 *
 *   - buildCompanyPipelinesPayload(state) — pipeline 에디터용 (templates, active agents)
 *   - buildCompanyStatusPayload(state) — sidebar chip (enabled, name, summary)
 *   - buildCompanyResumablePayload(items, state) — 재개 가능 세션 목록
 *
 * `_sendCompanyAgents` 는 95+ 줄짜리 큰 빌더라 다음 라운드에서 별도로 다룬다.
 */

/**
 * Pipeline 에디터가 그릴 때 필요한 모든 메타데이터를 한 페이로드로:
 *   - 등록된 pipelines + 현재 active id
 *   - 직군 라벨/순서 (UI 가 enum 값을 모르므로 백엔드가 결정)
 *   - 직군별 활성 에이전트 슬림 정보 (cascading dropdown 채우기용)
 *   - template 카탈로그 (가벼운 메타만, stages 는 stamp 시점에 따로 요청)
 */
export function buildCompanyPipelinesPayload(state: CompanyState) {
    const byCategory = listActiveAgentsByCategory(state);
    const slimByCategory: Record<string, Array<{ id: string; name: string; emoji: string }>> = {};
    for (const [cat, defs] of Object.entries(byCategory)) {
        slimByCategory[cat] = defs.map((d) => ({ id: d.id, name: d.name, emoji: d.emoji }));
    }
    const templates = PIPELINE_TEMPLATES.map((t) => ({
        templateId: t.templateId,
        name: t.name,
        description: t.description,
        stageCount: t.stages.length,
        suggestedPipelineId: t.suggestedPipelineId,
        suggestedPipelineName: t.suggestedPipelineName,
    }));
    return {
        type: 'companyPipelines' as const,
        value: {
            pipelines: state.pipelines ?? {},
            activePipelineId: state.activePipelineId ?? null,
            roleCategoryLabels: ROLE_CATEGORY_LABELS,
            roleCategoryOrder: ROLE_CATEGORY_ORDER,
            activeAgentsByCategory: slimByCategory,
            templates,
        },
    };
}

/**
 * Sidebar chip 의 active/inactive + 회사명 + 한 줄 요약 + 활성 에이전트 id 목록.
 * 스코프 프리셋 활성 id 도 동봉 — sidebar segmented control 이 현재 선택을 표시.
 */
export function buildCompanyStatusPayload(state: CompanyState) {
    return {
        type: 'companyStatus' as const,
        value: {
            enabled: state.enabled,
            companyName: state.companyName,
            summary: summarizeForChip(state),
            activeAgentIds: state.activeAgentIds,
            modelOverrides: state.modelOverrides,
            activePipelineId: state.activePipelineId ?? null,
        },
    };
}

/**
 * Manage panel 의 agent catalogue 페이로드. built-in + custom 합쳐 ordered list 로
 * 직렬화하고, 각 엔트리에는 *기본값(baseDef) + 현재값(effective) + override 플래그*
 * 까지 보내 UI 가 "수정됨" 표시 + Reset 버튼 + Edit 폼의 dirty 비교를 한 페이로드
 * 만으로 그릴 수 있게 한다.
 *
 * `pipelineUsage` 는 각 agent id 별로 *어떤 pipeline 들이 그를 stage 에 쓰고 있는가*
 * 를 미리 집계 — 비어 있으면 삭제 가능, 한 개 이상이면 UI 가 삭제 버튼 disabled +
 * tooltip 에 pipeline 이름 노출.
 *
 * `hiddenBuiltinIds` 는 사용자가 숨긴 빌트인들 — "복원" 옵션을 위해 한 줄 메타로
 * 같이 보낸다.
 */
export function buildCompanyAgentsPayload(state: CompanyState, globalKnowledgeMixWeight: number) {
    const hiddenSet = new Set(state.hiddenBuiltinIds ?? []);
    const builtinIds = COMPANY_AGENT_ORDER.filter((id) => !!COMPANY_AGENTS[id] && !hiddenSet.has(id));
    const customIds = state.customAgents ? Object.keys(state.customAgents) : [];
    const orderedIds = [...builtinIds, ...customIds];

    const pipelineUsage: Record<string, string[]> = {};
    for (const p of Object.values(state.pipelines ?? {})) {
        for (const s of p.stages) {
            if (!s.agentId) continue;
            (pipelineUsage[s.agentId] = pipelineUsage[s.agentId] ?? []).push(p.name || p.id);
        }
    }

    const renderEntry = (id: string) => {
        const builtin = COMPANY_AGENTS[id];
        const custom = state.customAgents?.[id];
        const baseDef = builtin ?? custom;
        if (!baseDef) return null;
        // 직군 override 적용된 effective def. dropdown 이 옳은 선택값 보이려면 override 결과 송신.
        const effective = resolveAgent(state, id) ?? baseDef;
        const isCustom = !builtin;
        const override = state.promptOverrides[id] || {};
        const kmOverride = state.knowledgeMixOverrides[id];
        const hasKmOverride = typeof kmOverride === 'number';
        const roleOverride = state.roleCategoryOverrides?.[id];
        const displayOv = state.displayOverrides?.[id] || {};
        return {
            id,
            name: effective.name,
            role: effective.role,
            emoji: effective.emoji,
            color: effective.color,
            alwaysOn: !!effective.alwaysOn,
            custom: isCustom,
            active: id === 'ceo' || state.activeAgentIds.includes(id),
            modelOverride: state.modelOverrides[id] || '',
            defaultTagline: baseDef.tagline,
            defaultSpecialty: baseDef.specialty,
            defaultPersona: baseDef.persona || '',
            tagline: override.tagline || baseDef.tagline,
            specialty: override.specialty || baseDef.specialty,
            persona: override.persona || baseDef.persona || '',
            personaOverridden: !!override.persona,
            specialtyOverridden: !!override.specialty,
            taglineOverridden: !!override.tagline,
            // Display override — Edit 폼이 default vs current 비교해 dirty 표시할 수 있게
            // baseDef 의 원본 값도 같이 보낸다.
            defaultName: baseDef.name,
            defaultRole: baseDef.role,
            defaultEmoji: baseDef.emoji,
            defaultColor: baseDef.color,
            nameOverridden: !!displayOv.name,
            roleOverridden: !!displayOv.role,
            emojiOverridden: !!displayOv.emoji,
            colorOverridden: !!displayOv.color,
            // 직군: effective + base default + override 플래그
            roleCategory: effective.roleCategory,
            defaultRoleCategory: baseDef.roleCategory,
            roleCategoryOverridden: !!roleOverride && roleOverride !== baseDef.roleCategory,
            knowledgeMixOverride: hasKmOverride ? kmOverride : null,
            effectiveKnowledgeMixWeight: hasKmOverride ? kmOverride : globalKnowledgeMixWeight,
            usedInPipelines: pipelineUsage[id] ? [...new Set(pipelineUsage[id])] : [],
        };
    };

    const agents = orderedIds.map(renderEntry).filter((x): x is NonNullable<ReturnType<typeof renderEntry>> => !!x);
    const hiddenBuiltins = (state.hiddenBuiltinIds ?? [])
        .map((id) => {
            const def = COMPANY_AGENTS[id];
            if (!def) return null;
            return { id, name: def.name, role: def.role, emoji: def.emoji };
        })
        .filter((x): x is { id: string; name: string; role: string; emoji: string } => !!x);

    return {
        type: 'companyAgents' as const,
        value: {
            companyName: state.companyName,
            globalKnowledgeMixWeight,
            agents,
            hiddenBuiltins,
            // 직군 라벨 사전 + 표시 순서 — webview 는 enum 값을 모르므로 백엔드가 결정.
            roleCategoryLabels: ROLE_CATEGORY_LABELS,
            roleCategoryOrder: ROLE_CATEGORY_ORDER,
        },
    };
}

/**
 * 재개 가능 세션 list 페이로드. 세션 raw 에 pipeline name 을 resolve 해서 함께
 * 보냄 — webview 가 id 만 받으면 dropdown 에 "id" 만 표시되는 회귀 차단.
 */
export function buildCompanyResumablePayload(items: CompanyResumeState[], state: CompanyState) {
    return {
        type: 'companyResumable' as const,
        value: {
            items: items.map((s) => ({
                timestamp: s.timestamp,
                userPrompt: s.userPrompt.slice(0, 200),
                pipelineId: s.pipelineId,
                pipelineName: s.pipelineId
                    ? (state.pipelines?.[s.pipelineId]?.name ?? s.pipelineId)
                    : null,
                completedCount: s.agentOutputs.length,
                totalCount: s.plan.tasks.length,
                status: s.status,
                abortReason: s.abortReason ?? '',
                lastUpdatedAt: s.lastUpdatedAt,
                startedAt: s.startedAt,
            })),
        },
    };
}
