import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';
import type { SidebarChatProvider } from '../sidebarProvider';
import { runConnectGoogleCalendarIcal, runConnectGoogleCalendarOAuth } from './calendarSetup';

/**
 * Provider 위에 얇게 얹힌 명령 묶음 — architecture / company / calendar / devil.
 * 4 클러스터 모두 `provider._X()` 메서드를 직접 호출하거나 외부 마법사를 부르는
 * thin shell 이라 deps 가 거의 동일 (`context` + `provider getter`).
 *
 * 옛 코드: extension.ts 의 `activate()` 안 100줄 inline command block. 분리해
 * (a) activate() 길이 축소, (b) command 추가/수정 시 한 파일만 수정, (c) 새 명령
 * cluster 추가 시 같은 패턴 (`registerXCommands(context, deps)`) 으로 일관.
 *
 * `provider` 는 getter 로 받음 — activate() 가 provider 인스턴스를 변수에 할당
 * 한 후 commands 가 호출되므로, 등록 시점엔 아직 undefined 일 수 있다. getter 가
 * 호출 시점의 최신 값을 반환.
 */
export interface ProviderCommandsDeps {
    /** activate() 의 `let provider` 를 호출 시점에 회수. registration 시점엔 undefined 일 수 있음. */
    getProvider: () => SidebarChatProvider | undefined;
}

export function registerProviderCommands(
    context: vscode.ExtensionContext,
    deps: ProviderCommandsDeps,
): vscode.Disposable[] {
    return [
        // ── Project Architecture (Feature 2) ─────────────────────────────────
        // Thin shells — 모든 state mutation 은 provider 가 갖고 있게 (chip / watcher).
        vscode.commands.registerCommand('g1nation.architecture.refresh', async () => {
            const provider = deps.getProvider();
            if (!provider) return;
            await provider._refreshArchitecture();
            vscode.window.showInformationMessage('Astra: Project architecture context refreshed.');
        }),
        vscode.commands.registerCommand('g1nation.architecture.detach', async () => {
            const provider = deps.getProvider();
            if (!provider) return;
            await provider._detachArchitecture();
            vscode.window.showInformationMessage('Astra: Project architecture auto-attach turned off.');
        }),
        vscode.commands.registerCommand('g1nation.architecture.attach', async () => {
            const provider = deps.getProvider();
            if (!provider) return;
            await provider._attachArchitecture();
            vscode.window.showInformationMessage('Astra: Project architecture auto-attach turned on.');
        }),
        vscode.commands.registerCommand('g1nation.architecture.open', async () => {
            const provider = deps.getProvider();
            if (!provider) return;
            await provider._openArchitectureDoc();
        }),
        // Active subproject 재해상 — 사용자가 서브폴더 사이 editor 를 옮기면 chip 갱신.
        // 400ms debounce — 빠른 editor flick 이 watcher 를 churn 시키지 않게.
        // resync 자체는 idempotent — 활성 서브프로젝트가 안 바뀌면 noop.
        (() => {
            let timer: NodeJS.Timeout | undefined;
            return vscode.window.onDidChangeActiveTextEditor(() => {
                const provider = deps.getProvider();
                if (!provider) return;
                if (timer) clearTimeout(timer);
                timer = setTimeout(() => {
                    provider._sendArchitectureStatus().catch(() => { /* chip 은 best-effort */ });
                }, 400);
            });
        })(),

        // ── 1인 기업 (Company) Mode ──────────────────────────────────────────
        vscode.commands.registerCommand('g1nation.company.toggle', async () => {
            const provider = deps.getProvider();
            if (!provider) return;
            const { readCompanyState, setCompanyEnabled } = await import('../features/company');
            const cur = readCompanyState(context);
            const next = await setCompanyEnabled(context, !cur.enabled);
            await provider._sendCompanyStatus();
            vscode.window.showInformationMessage(`Astra: 1인 기업 모드 ${next.enabled ? 'ON' : 'OFF'}`);
        }),
        vscode.commands.registerCommand('g1nation.company.manage', async () => {
            const provider = deps.getProvider();
            if (!provider) return;
            await vscode.commands.executeCommand('g1nation-v2-view.focus');
            provider._view?.webview.postMessage({ type: 'openCompanyManageOverlay' });
            await provider._sendCompanyAgents();
            await provider._sendCompanyResumable();
        }),
        vscode.commands.registerCommand('g1nation.company.openSessions', async () => {
            const { resolveCompanyBase } = await import('../features/company');
            const base = resolveCompanyBase(context);
            const target = path.join(base, 'sessions');
            try {
                if (!fs.existsSync(target)) fs.mkdirSync(target, { recursive: true });
                await vscode.env.openExternal(vscode.Uri.file(target));
            } catch (e: any) {
                vscode.window.showErrorMessage(`Sessions 폴더 열기 실패: ${e?.message ?? e}`);
            }
        }),
        vscode.commands.registerCommand('g1nation.company.pixelOffice.open', () => {
            // 사이드바 mini 패널과 별도로 editor area 에 전체 사무실 뷰. 같은
            // pixelOfficeUpdate 스트림 공유 → 백엔드 변경 최소.
            deps.getProvider()?.openPixelOfficePanel();
        }),

        // ── Google Calendar (iCal 읽기 / OAuth 쓰기) ────────────────────────
        vscode.commands.registerCommand('g1nation.calendar.connect', async () => {
            await runConnectGoogleCalendarIcal(context);
        }),
        vscode.commands.registerCommand('g1nation.calendar.refresh', async () => {
            const { refreshCalendarCache } = await import('../features/calendar');
            const r = await refreshCalendarCache(context);
            if (r.ok) {
                vscode.window.showInformationMessage(`📅 캘린더 ${r.count}개 일정을 회사 컨텍스트에 동기화했습니다.`);
            } else {
                vscode.window.showErrorMessage(r.error || 'Calendar 새로고침 실패');
            }
        }),
        vscode.commands.registerCommand('g1nation.calendar.connectOAuth', async () => {
            await runConnectGoogleCalendarOAuth(context);
        }),

        // ── Devil Agent (도현) — 답변 직후 비판적 반박 토글 ─────────────────
        vscode.commands.registerCommand('g1nation.devilAgent.toggle', async () => {
            const { isDevilAgentEnabled, setDevilAgentEnabled, DEVIL_PERSONA_NAME } =
                await import('../features/devilAgent');
            const wasOn = isDevilAgentEnabled();
            await setDevilAgentEnabled(!wasOn);
            const nowOn = !wasOn;
            vscode.window.showInformationMessage(
                nowOn
                    ? `🎭 ${DEVIL_PERSONA_NAME} 활성화됨 — 이제 매 답변 뒤에 비판적 반박 카드가 떠요.`
                    : `🎭 ${DEVIL_PERSONA_NAME} 비활성화됨.`,
            );
        }),
    ];
}
