import type {
  ArenaState,
  ClosedPaneEntry,
  HtmlArtifactState,
  MarkdownArtifactState,
  OrchestratorState,
  WorkspacePane,
  WorkspaceState,
  WorkspaceTabKind,
} from '@/api/types';

export const TERM_TAB_PREFIX = 'term_';

export const MAX_CLOSED = 10;

export const SAVE_DEBOUNCE_MS = 300;

export const LEGACY_STORAGE_KEY = 'boocode.workspace.panes';

export function generateId(): string {
  return crypto.randomUUID();
}

export function generateTermTabId(): string {
  return `${TERM_TAB_PREFIX}${generateId()}`;
}

export function paneTabKinds(pane: WorkspacePane): WorkspaceTabKind[] {
  if (pane.tabKinds && pane.tabKinds.length === pane.chatIds.length) return pane.tabKinds;
  const fallback: WorkspaceTabKind =
    pane.kind === 'coder' || pane.kind === 'terminal' ? pane.kind : 'chat';
  return pane.chatIds.map(() => fallback);
}

export function rebuildPane(
  pane: WorkspacePane,
  ids: string[],
  kinds: WorkspaceTabKind[],
  desiredActive: number,
): WorkspacePane {
  if (ids.length === 0) {
    return {
      ...pane,
      kind: 'empty',
      chatId: undefined,
      chatIds: [],
      tabKinds: [],
      activeChatIdx: -1,
      markdown_artifact_state: undefined,
      html_artifact_state: undefined,
    };
  }
  const idx = Math.max(0, Math.min(desiredActive, ids.length - 1));
  return {
    ...pane,
    kind: kinds[idx]!,
    chatId: ids[idx],
    chatIds: ids,
    tabKinds: kinds,
    activeChatIdx: idx,
  };
}

export function filterTabs(
  pane: WorkspacePane,
  keep: (id: string, idx: number) => boolean,
): { ids: string[]; kinds: WorkspaceTabKind[]; removedTermIds: string[] } {
  const kinds = paneTabKinds(pane);
  const ids: string[] = [];
  const nextKinds: WorkspaceTabKind[] = [];
  const removedTermIds: string[] = [];
  pane.chatIds.forEach((id, i) => {
    if (keep(id, i)) {
      ids.push(id);
      nextKinds.push(kinds[i]!);
    } else if (kinds[i] === 'terminal') {
      removedTermIds.push(id);
    }
  });
  return { ids, kinds: nextKinds, removedTermIds };
}

export function emptyPane(id: string = generateId()): WorkspacePane {
  return { id, kind: 'empty', chatIds: [], tabKinds: [], activeChatIdx: -1 };
}

export function chatPane(chatId: string): WorkspacePane {
  return { id: generateId(), kind: 'chat', chatId, chatIds: [chatId], tabKinds: ['chat'], activeChatIdx: 0 };
}

export function appendClosed(stack: ClosedPaneEntry[], pane: WorkspacePane): ClosedPaneEntry[] {
  if (pane.kind === 'empty' || pane.kind === 'settings') return stack;
  if (pane.chatIds.length === 0) return stack;
  const entry = { kind: pane.kind, chatIds: [...pane.chatIds], tabKinds: [...paneTabKinds(pane)], activeChatIdx: pane.activeChatIdx };
  const top = stack[stack.length - 1];
  if (
    top &&
    top.kind === entry.kind &&
    top.activeChatIdx === entry.activeChatIdx &&
    top.chatIds.length === entry.chatIds.length &&
    top.chatIds.every((id, i) => id === entry.chatIds[i])
  ) {
    return stack;
  }
  const next = [...stack, entry];
  if (next.length > MAX_CLOSED) next.splice(0, next.length - MAX_CLOSED);
  return next;
}

export function chatNameForPaneKind(kind: 'coder' | 'terminal'): string {
  return kind === 'coder' ? 'BooCoder' : 'Terminal';
}

export function activePaneChatId(pane: WorkspacePane): string | undefined {
  const idx = pane.activeChatIdx ?? 0;
  if (idx >= 0 && pane.chatIds?.[idx]) return pane.chatIds[idx];
  return pane.chatId;
}

function settingsPane(id: string = generateId()): WorkspacePane {
  return { id, kind: 'settings', chatIds: [], activeChatIdx: -1 };
}

export { settingsPane };

export function markdownArtifactPane(state: MarkdownArtifactState): WorkspacePane {
  return {
    id: generateId(),
    kind: 'markdown_artifact',
    chatIds: [],
    activeChatIdx: -1,
    markdown_artifact_state: state,
  };
}

export function htmlArtifactPane(state: HtmlArtifactState): WorkspacePane {
  return {
    id: generateId(),
    kind: 'html_artifact',
    chatIds: [],
    activeChatIdx: -1,
    html_artifact_state: state,
  };
}

export function orchestratorPane(state: OrchestratorState): WorkspacePane {
  return {
    id: generateId(),
    kind: 'orchestrator',
    chatIds: [],
    activeChatIdx: -1,
    orchestrator_state: state,
  };
}

export function arenaPane(state: ArenaState): WorkspacePane {
  return {
    id: generateId(),
    kind: 'arena',
    chatIds: [],
    activeChatIdx: -1,
    arena_state: state,
  };
}

function normalizePaneKind(pane: WorkspacePane): WorkspacePane {
  let p = pane;
  if ((p.kind as string) === 'agent') p = { ...p, kind: 'coder' };
  const tabbed = p.kind === 'chat' || p.kind === 'coder' || p.kind === 'terminal';
  if (!tabbed) return p;
  if (p.kind === 'terminal' && (!p.tabKinds || p.tabKinds.length === 0)) {
    return { ...p, chatIds: [p.id], tabKinds: ['terminal'], chatId: p.id, activeChatIdx: 0 };
  }
  if (!p.tabKinds || p.tabKinds.length !== p.chatIds.length) {
    const k: WorkspaceTabKind = p.kind === 'coder' ? 'coder' : p.kind === 'terminal' ? 'terminal' : 'chat';
    return { ...p, tabKinds: p.chatIds.map(() => k) };
  }
  return p;
}

export function normalizePanes(panes: WorkspacePane[]): WorkspacePane[] {
  return panes.map(normalizePaneKind);
}

export { normalizePaneKind };

export function persistablePanes(panes: WorkspacePane[]): WorkspacePane[] {
  return normalizePanes(panes).filter((p) => p.kind !== 'settings');
}

export function toWorkspaceState(raw: unknown): WorkspaceState {
  if (Array.isArray(raw)) {
    return { panes: raw as WorkspacePane[], tabNumbers: {}, nextTabNumber: 1, closedPaneStack: [] };
  }
  if (raw && typeof raw === 'object' && Array.isArray((raw as WorkspaceState).panes)) {
    const env = raw as WorkspaceState;
    return {
      panes: env.panes,
      tabNumbers: env.tabNumbers ?? {},
      nextTabNumber: env.nextTabNumber ?? 1,
      closedPaneStack: env.closedPaneStack ?? [],
    };
  }
  return { panes: [], tabNumbers: {}, nextTabNumber: 1, closedPaneStack: [] };
}

export function nonSettingsCount(panes: WorkspacePane[]): number {
  return panes.reduce((n, p) => n + (p.kind === 'settings' ? 0 : 1), 0);
}

export function readLegacyPanes(sessionId: string): WorkspacePane[] | null {
  try {
    const raw = localStorage.getItem(`${LEGACY_STORAGE_KEY}.${sessionId}`);
    if (!raw) return null;
    const parsed = JSON.parse(raw) as WorkspacePane[];
    if (!Array.isArray(parsed) || parsed.length === 0) return null;
    return parsed;
  } catch {
    return null;
  }
}
