import { SidebarChatProvider } from '../sidebarProvider';

/**
 * 1인 기업 모드 도메인 메시지 핸들러.
 *
 * 의도: chatHandlers 가 한때 모든 카테고리의 webview 메시지를 처리했는데, 회사
 * 모드가 ~30개의 메시지 타입(getCompanyStatus / setCompanyAgentDisplay / resume /
 * alignment / approval / pipeline / pixelOffice …)을 끌고 들어오면서 single
 * file 이 700+ 줄로 부풀었다. chronicleHandlers 처럼 도메인별 분리 패턴이 이미
 * 시작돼 있어서 회사 모드도 같은 모양으로 떼어낸다.
 *
 * 처리한 케이스는 true 반환 — chatHandlers 가 이걸 보고 LLM fallback 으로 안 흘림.
 * 해당 도메인이 아니면 false → chatHandlers 가 그 다음 분기 진행.
 */
export async function handleCompanyMessage(
    provider: SidebarChatProvider,
    data: any,
): Promise<boolean> {
    switch (data.type) {
        case 'getCompanyStatus':
            await provider._sendCompanyStatus();
            return true;
        case 'getCompanyAgents':
            await provider._sendCompanyAgents();
            return true;
        case 'getCompanyResumable':
            await provider._sendCompanyResumable();
            return true;
        case 'resumeCompanyTurn': {
            // 사용자가 "이어서 진행" 칩을 눌렀을 때. timestamp만 받아서 디스크의
            // _resume.json을 읽고 그 다음 stage부터 dispatch가 이어진다.
            const ts = typeof data.timestamp === 'string' ? data.timestamp : '';
            if (!ts) return true;
            // userPrompt 인자는 resume 경로에서 무시되지만(plan은 디스크에서 복원)
            // 시그니처 일관성을 위해 dummy 값을 전달.
            void provider._runCompanyTurn('', ts);
            return true;
        }
        case 'discardResumableSession': {
            // 사용자가 명시적으로 재개 항목을 버리고 싶을 때 — resume 파일을 'failed'로
            // 마킹해서 listResumable에서 자동 제외. markResumeStatus가 안전한 idempotent
            // 작업이라 별도 검증 불필요.
            const ts = typeof data.timestamp === 'string' ? data.timestamp : '';
            if (!ts) return true;
            try {
                const { resolveSessionDir } = await import('../features/company');
                const { markResumeStatus } = await import('../features/company/resumeStore');
                markResumeStatus(resolveSessionDir(provider._context, ts), 'failed', 'discarded-by-user');
            } catch { /* 무시 — 다음 푸시에서 자연 복구 */ }
            await provider._sendCompanyResumable();
            return true;
        }
        case 'setCompanyEnabled': {
            const { setCompanyEnabled } = await import('../features/company');
            await setCompanyEnabled(provider._context, !!data.value);
            await provider._sendCompanyStatus();
            return true;
        }
        case 'setCompanyName': {
            const { setCompanyName } = await import('../features/company');
            await setCompanyName(provider._context, typeof data.value === 'string' ? data.value : '');
            await provider._sendCompanyStatus();
            return true;
        }
        case 'setCompanyActiveAgents': {
            const { setActiveAgents } = await import('../features/company');
            const ids = Array.isArray(data.value)
                ? data.value.filter((v: unknown): v is string => typeof v === 'string')
                : [];
            await setActiveAgents(provider._context, ids);
            await provider._sendCompanyStatus();
            await provider._sendCompanyAgents();
            return true;
        }
        case 'setCompanyAgentModel': {
            const { setAgentModelOverride } = await import('../features/company');
            const agentId = typeof data.agentId === 'string' ? data.agentId : '';
            const model = typeof data.model === 'string' ? data.model : '';
            if (agentId) {
                await setAgentModelOverride(provider._context, agentId, model);
                await provider._sendCompanyAgents();
            }
            return true;
        }
        case 'setCompanyAgentDisplay': {
            // 이름/역할/이모지/색상 override. 페이로드는 setCompanyAgentPrompt와
            // 동일한 패턴 — null이면 전체 reset, 각 필드 빈 문자열이면 그 필드만 reset.
            const { setAgentDisplayOverride } = await import('../features/company');
            const agentId = typeof data.agentId === 'string' ? data.agentId : '';
            if (!agentId) return true;
            const v = data.override;
            const override = v === null
                ? null
                : {
                    name: typeof v?.name === 'string' ? v.name : undefined,
                    role: typeof v?.role === 'string' ? v.role : undefined,
                    emoji: typeof v?.emoji === 'string' ? v.emoji : undefined,
                    color: typeof v?.color === 'string' ? v.color : undefined,
                };
            const result = await setAgentDisplayOverride(provider._context, agentId, override);
            provider._view?.webview.postMessage({
                type: 'setCompanyAgentDisplayResult',
                value: result.ok ? { ok: true, agentId } : { ok: false, reason: result.reason },
            });
            if (result.ok) await provider._sendCompanyAgents();
            return true;
        }
        case 'setCompanyAgentRoleCategory': {
            // Override an agent's 직군. Empty / null payload value reverts to
            // the def's own roleCategory. CEO is rejected by the backend.
            const { setAgentRoleCategory } = await import('../features/company');
            const agentId = typeof data.agentId === 'string' ? data.agentId : '';
            if (!agentId) return true;
            const cat = (typeof data.value === 'string' && data.value.trim()) ? data.value.trim() : null;
            const result = await setAgentRoleCategory(provider._context, agentId, cat as any);
            provider._view?.webview.postMessage({
                type: 'setCompanyAgentRoleCategoryResult',
                value: result.ok ? { ok: true, agentId } : { ok: false, reason: result.reason },
            });
            if (result.ok) await provider._sendCompanyAgents();
            return true;
        }
        case 'setCompanyAgentKnowledgeMix': {
            // Per-agent Knowledge Mix override. `null`/missing value falls
            // back to the global slider. The dispatcher reads this on the
            // *next* turn — no restart required.
            const { setAgentKnowledgeMix } = await import('../features/company');
            const agentId = typeof data.agentId === 'string' ? data.agentId : '';
            if (!agentId) return true;
            const raw = data.value;
            const weight = (raw === null || raw === undefined || !Number.isFinite(Number(raw)))
                ? null
                : Math.max(0, Math.min(100, Math.round(Number(raw))));
            await setAgentKnowledgeMix(provider._context, agentId, weight);
            await provider._sendCompanyAgents();
            return true;
        }
        case 'setCompanyAgentPrompt': {
            // Patch one agent's persona / specialty / tagline. Each field is
            // optional in the payload; passing an *empty string* explicitly
            // clears that field (back to the default from `agents.ts`).
            // Sending `null` for the whole override resets every field at once.
            const { setAgentPromptOverride } = await import('../features/company');
            const agentId = typeof data.agentId === 'string' ? data.agentId : '';
            if (!agentId) return true;
            const v = data.override;
            const override = v === null
                ? null
                : {
                    persona: typeof v?.persona === 'string' ? v.persona : undefined,
                    specialty: typeof v?.specialty === 'string' ? v.specialty : undefined,
                    tagline: typeof v?.tagline === 'string' ? v.tagline : undefined,
                };
            await setAgentPromptOverride(provider._context, agentId, override);
            await provider._sendCompanyAgents();
            return true;
        }
        case 'addCompanyAgent': {
            // User-defined agent. Payload: { def: CompanyAgentDef }. Returns
            // an `addCompanyAgentResult` so the UI overlay can keep its form
            // open + show an error when validation fails (id collision etc.).
            const { addCustomAgent } = await import('../features/company');
            const def = data.def;
            const result = await addCustomAgent(provider._context, def ?? {});
            provider._view?.webview.postMessage({
                type: 'addCompanyAgentResult',
                value: result.ok
                    ? { ok: true, agentId: def?.id }
                    : { ok: false, reason: result.reason },
            });
            if (result.ok) {
                await provider._sendCompanyStatus();
                await provider._sendCompanyAgents();
            }
            return true;
        }
        case 'deleteCompanyAgent': {
            // Delete any agent (built-in via hide, custom via outright removal).
            // Backend checks pipeline usage and refuses if any stage references it.
            const { removeCompanyAgent } = await import('../features/company');
            const agentId = typeof data.agentId === 'string' ? data.agentId : '';
            if (!agentId) return true;
            const result = await removeCompanyAgent(provider._context, agentId);
            provider._view?.webview.postMessage({
                type: 'deleteCompanyAgentResult',
                value: result.ok
                    ? { ok: true, agentId, kind: result.kind }
                    : { ok: false, agentId, reason: result.reason },
            });
            if (result.ok) {
                await provider._sendCompanyStatus();
                await provider._sendCompanyAgents();
            }
            return true;
        }
        case 'restoreHiddenAgent': {
            // Bring a previously-hidden built-in back into the manage panel.
            const { restoreHiddenAgent } = await import('../features/company');
            const agentId = typeof data.agentId === 'string' ? data.agentId : '';
            if (!agentId) return true;
            const result = await restoreHiddenAgent(provider._context, agentId);
            provider._view?.webview.postMessage({
                type: 'restoreHiddenAgentResult',
                value: result.ok ? { ok: true, agentId } : { ok: false, reason: result.reason },
            });
            if (result.ok) {
                await provider._sendCompanyStatus();
                await provider._sendCompanyAgents();
            }
            return true;
        }
        case 'getCompanyPipelines':
            await provider._sendCompanyPipelines();
            return true;
        case 'upsertCompanyPipeline': {
            const { upsertPipeline } = await import('../features/company');
            const result = await upsertPipeline(provider._context, data.def ?? {});
            provider._view?.webview.postMessage({
                type: 'upsertCompanyPipelineResult',
                value: result.ok ? { ok: true } : { ok: false, reason: result.reason },
            });
            if (result.ok) await provider._sendCompanyPipelines();
            return true;
        }
        case 'deleteCompanyPipeline': {
            const { deletePipeline } = await import('../features/company');
            const pid = typeof data.pipelineId === 'string' ? data.pipelineId : '';
            if (!pid) return true;
            const result = await deletePipeline(provider._context, pid);
            provider._view?.webview.postMessage({
                type: 'deleteCompanyPipelineResult',
                value: result.ok ? { ok: true, pipelineId: pid } : { ok: false, reason: result.reason },
            });
            if (result.ok) await provider._sendCompanyPipelines();
            return true;
        }
        case 'getCompanyPipelineTemplate': {
            // Returns a template's stages so the editor can pre-fill the form.
            const { getPipelineTemplate } = await import('../features/company');
            const tplId = typeof data.templateId === 'string' ? data.templateId : '';
            const tpl = getPipelineTemplate(tplId);
            provider._view?.webview.postMessage({
                type: 'companyPipelineTemplateContent',
                value: tpl ? {
                    templateId: tpl.templateId,
                    suggestedPipelineId: tpl.suggestedPipelineId,
                    suggestedPipelineName: tpl.suggestedPipelineName,
                    stages: tpl.stages,
                } : null,
            });
            return true;
        }
        case 'getPixelOfficeState':
            // webview가 처음 로드되었거나 사용자가 토글 ON 했을 때 캐시된
            // 현재 상태를 다시 받기 위한 요청. read-only.
            provider.pixelOfficeResend();
            return true;
        case 'openPixelOfficePanel':
            // 사이드바 mini Pixel Office의 ⛶ 버튼 → editor area에 전체보기 panel 열기.
            provider.openPixelOfficePanel();
            return true;
        case 'respondCompanyAlignment': {
            // alignment 카드 버튼: 'proceed' = 현 contract로 dispatch, 'cancel' = 폐기.
            const decision = typeof data.decision === 'string' ? data.decision : '';
            if (decision === 'proceed') {
                await provider._proceedWithCurrentAlignment();
            } else if (decision === 'cancel') {
                provider.cancelPendingAlignment();
            }
            return true;
        }
        case 'respondCompanyApproval': {
            // Webview의 승인 카드 버튼 클릭 → dispatcher의 await 해제.
            // payload: { stageId, decision: 'approve' | 'revise' | 'abort', comment? }
            const stageId = typeof data.stageId === 'string' ? data.stageId : '';
            const decision = typeof data.decision === 'string' ? data.decision : '';
            if (!stageId || !['approve', 'revise', 'abort'].includes(decision)) return true;
            let payload: any;
            if (decision === 'approve') payload = { kind: 'approve' };
            else if (decision === 'abort') payload = { kind: 'abort' };
            else payload = { kind: 'revise', comment: typeof data.comment === 'string' ? data.comment : '' };
            provider.resolveApprovalGate(stageId, payload);
            return true;
        }
        case 'setActiveCompanyPipeline': {
            const { setActivePipeline } = await import('../features/company');
            const pid = typeof data.pipelineId === 'string' && data.pipelineId.trim()
                ? data.pipelineId.trim()
                : null;
            const result = await setActivePipeline(provider._context, pid);
            provider._view?.webview.postMessage({
                type: 'setActiveCompanyPipelineResult',
                value: result.ok ? { ok: true, pipelineId: pid } : { ok: false, reason: result.reason },
            });
            if (result.ok) await provider._sendCompanyPipelines();
            return true;
        }
        case 'setCompanyScopePreset': {
            // 스코프 프리셋 클릭 — templateId (plan-only / dev-only / full-product-dev) 받아서:
            //   1) suggestedPipelineId 의 pipeline 이 state.pipelines 에 없으면 template stamp
            //   2) activePipelineId 를 그 id 로 설정
            // 이미 stamp 된 pipeline 이라면 stage 사용자 편집을 *유지* (활성화만).
            const { getPipelineTemplate, upsertPipeline, setActivePipeline, readCompanyState } =
                await import('../features/company');
            const tplId = typeof data.templateId === 'string' ? data.templateId : '';
            const tpl = getPipelineTemplate(tplId);
            if (!tpl) {
                provider._view?.webview.postMessage({
                    type: 'setCompanyScopePresetResult',
                    value: { ok: false, reason: `알 수 없는 템플릿: ${tplId}` },
                });
                return true;
            }
            const state = readCompanyState(provider._context);
            if (!state.pipelines || !state.pipelines[tpl.suggestedPipelineId]) {
                const stampDef = {
                    id: tpl.suggestedPipelineId,
                    name: tpl.suggestedPipelineName,
                    // stage 는 deep clone — 템플릿 read-only 원본 보호.
                    stages: tpl.stages.map((s) => ({ ...s })),
                };
                const stamp = await upsertPipeline(provider._context, stampDef);
                if (!stamp.ok) {
                    provider._view?.webview.postMessage({
                        type: 'setCompanyScopePresetResult',
                        value: { ok: false, reason: stamp.reason },
                    });
                    return true;
                }
            }
            const activate = await setActivePipeline(provider._context, tpl.suggestedPipelineId);
            provider._view?.webview.postMessage({
                type: 'setCompanyScopePresetResult',
                value: activate.ok
                    ? { ok: true, pipelineId: tpl.suggestedPipelineId, templateId: tplId }
                    : { ok: false, reason: activate.reason },
            });
            if (activate.ok) {
                await provider._sendCompanyStatus();
                await provider._sendCompanyPipelines();
            }
            return true;
        }
        default:
            return false;
    }
}
