import * as vscode from 'vscode';
import type { AgentWorkState } from '../../features/company';
import type { OfficeActivityItem } from '../../features/astraOffice';

/**
 * Pixel Office 의 *상태 컨테이너* — webview 송신/이벤트 핸들링은 provider 에 남기고,
 * 4개로 흩어져 있던 raw state slot 만 한 객체로 묶는다.
 *
 * 옛 코드는 sidebarProvider 의 4개 slot 으로 분리돼 있어 (panel, currentState,
 * lastBubble Map, activity ring buffer) "panel 닫혔는데 ring buffer 가 안 비워졌다"
 * 같은 미묘한 stale state bug 가 발생할 위험이 있었음. 컨테이너로 묶어
 * resetForNewSession() 한 줄로 일괄 초기화 가능하게 만들었다.
 *
 * 왜 메서드들은 안 옮겼나: pixelOfficeOnTurnEvent 등은 webview 송신 + payload
 * 빌드 + ring buffer push 가 한 데 엮여 있어 이걸 manager 로 옮기면 webview send
 * callback 을 constructor 로 주입해야 하고 코드 양이 오히려 늘어남. State 만
 * 격리해도 god-file 의 state slot 13→9 라는 목표 효과는 달성.
 */
export class PixelOfficeState {
    /** 전체보기 webview panel — 사이드바 mini 와 별개 instance. */
    panel?: vscode.WebviewPanel;

    /** 현재 turn 의 누적 상태. broadcast 직전 patch 가 합쳐진 결과 보관. */
    current?: AgentWorkState;

    /** 같은 말풍선 텍스트 연속 출력 방지용 — key: "status:<s>" or "event:<e>". */
    private readonly lastBubbleByKey = new Map<string, string>();

    /** Activity ring buffer — officeSnapshot.activity 에 포함되는 누적 action-tag 결과. */
    private activityBuffer: OfficeActivityItem[] = [];

    private static readonly ACTIVITY_MAX = 32;

    /** 직전 말풍선 텍스트 조회. duplicate 회피 로직에서 사용. */
    getLastBubble(key: string): string | undefined {
        return this.lastBubbleByKey.get(key);
    }

    /** 말풍선 텍스트 기록. */
    setLastBubble(key: string, text: string): void {
        this.lastBubbleByKey.set(key, text);
    }

    /**
     * 현재 activity 버퍼 전체 조회 (snapshot 빌드에 사용). presenter 가
     * mutable 배열을 요구해 일단 같은 참조 그대로 반환 — 외부는 read-only 로
     * 다뤄야 함 (push 는 pushActivity() 만 사용).
     */
    getActivity(): OfficeActivityItem[] {
        return this.activityBuffer;
    }

    /**
     * Activity 항목 push + ring buffer cap 유지. agent-done 시 action-tag report
     * 가 여러 줄이면 한 번에 호출.
     */
    pushActivity(items: Array<{ agentId: string; text: string; kind?: 'ok' | 'warn' | 'err' | 'info' }>): void {
        if (!items?.length) return;
        const now = Date.now();
        for (const it of items) {
            this.activityBuffer.push({ ts: now, agentId: it.agentId, text: it.text, kind: it.kind });
        }
        if (this.activityBuffer.length > PixelOfficeState.ACTIVITY_MAX) {
            this.activityBuffer = this.activityBuffer.slice(-PixelOfficeState.ACTIVITY_MAX);
        }
    }

    /**
     * recentLogs ring buffer push — 새 라인을 현재 상태의 recentLogs 끝에 붙여
     * 최근 6개만 보존한 새 배열을 반환. 호출자는 이 배열을 다음 broadcast 의
     * `patch.recentLogs` 로 전달해 next state 에 반영.
     */
    appendLog(line: string): string[] {
        const cur = this.current?.recentLogs ?? [];
        return [...cur, line].slice(-6);
    }
}
