import { useState, useCallback } from 'react';
import {
  PendingAgentApproval,
  TerminalEntry,
  TerminalRequestState,
  WorkspaceTerminalState,
} from '../types/terminal';

const DEFAULT_WELCOME_MESSAGE =
  'MosaicIQ Financial Terminal v1.0\nUse /portfolio to open portfolio tools.\nSlash commands (/) clear the panel. Natural language builds a conversation.';

const createInitialTerminalState = (entryId: string): WorkspaceTerminalState => ({
  history: [
    {
      id: entryId,
      type: 'system',
      content: DEFAULT_WELCOME_MESSAGE,
      timestamp: new Date(),
    },
  ],
  chatSessionId: undefined,
  inputDraft: '',
  isProcessing: false,
  activeRequest: null,
  pendingApproval: null,
  scrollTop: 0,
  stickToBottom: true,
  collapsedThinkingEntryIds: [],
});

export interface Workspace {
  id: string;
  name: string;
  terminal: WorkspaceTerminalState;
  createdAt: Date;
  portfolioName?: string | null;
}

export const useTabs = () => {
  const [workspaces, setWorkspaces] = useState<Workspace[]>([
    {
      id: '1',
      name: 'Terminal 1',
      terminal: createInitialTerminalState('welcome'),
      createdAt: new Date(),
    },
  ]);
  const [activeWorkspaceId, setActiveWorkspaceId] = useState('1');

  const activeWorkspace = workspaces.find(w => w.id === activeWorkspaceId) || workspaces[0];

  const createWorkspace = useCallback((options?: { name?: string; terminal?: Partial<WorkspaceTerminalState> }) => {
    const id = Date.now().toString();
    const base = createInitialTerminalState(`welcome-${id}`);
    const terminal: WorkspaceTerminalState = options?.terminal
      ? { ...base, ...options.terminal }
      : base;

    const newWorkspace: Workspace = {
      id,
      name: options?.name ?? `Terminal ${workspaces.length + 1}`,
      terminal,
      createdAt: new Date(),
    };

    setWorkspaces(prev => [...prev, newWorkspace]);
    setActiveWorkspaceId(newWorkspace.id);
    return newWorkspace.id;
  }, [workspaces.length]);

  const closeWorkspace = useCallback((id: string) => {
    // Don't allow closing the last workspace
    if (workspaces.length === 1) return;

    setWorkspaces(prev => {
      const filtered = prev.filter(w => w.id !== id);

      // If we closed the active workspace, switch to another
      if (id === activeWorkspaceId) {
        const newActive = filtered[0];
        setActiveWorkspaceId(newActive.id);
      }

      return filtered;
    });
  }, [workspaces, activeWorkspaceId]);

  const setActiveWorkspace = useCallback((id: string) => {
    setActiveWorkspaceId(id);
  }, []);

  const updateWorkspaceTerminal = useCallback(
    (
      id: string,
      updater: (terminal: WorkspaceTerminalState) => WorkspaceTerminalState,
    ) => {
      setWorkspaces((prev) =>
        prev.map((workspace) =>
          workspace.id === id
            ? { ...workspace, terminal: updater(workspace.terminal) }
            : workspace,
        ),
      );
    },
    [],
  );

  const updateWorkspaceHistory = useCallback((id: string, history: TerminalEntry[]) => {
    updateWorkspaceTerminal(id, (terminal) => ({ ...terminal, history }));
  }, []);

  const appendWorkspaceEntry = useCallback((id: string, entry: TerminalEntry) => {
    // Appending in place keeps a stable entry id available for later stream updates.
    updateWorkspaceTerminal(id, (terminal) => ({
      ...terminal,
      history: [...terminal.history, entry],
    }));
  }, [updateWorkspaceTerminal]);

  const updateWorkspaceEntry = useCallback(
    (
      id: string,
      entryId: string,
      updater: (entry: TerminalEntry) => TerminalEntry,
    ) => {
      // Update a single entry without rebuilding unrelated workspaces.
      updateWorkspaceTerminal(id, (terminal) => ({
        ...terminal,
        history: terminal.history.map((entry) =>
          entry.id === entryId ? updater(entry) : entry,
        ),
      }));
    },
    [updateWorkspaceTerminal],
  );

  const clearWorkspace = useCallback((id: string) => {
    updateWorkspaceTerminal(id, (terminal) => ({
      ...terminal,
      history: [],
      chatSessionId: undefined,
      inputDraft: '',
      isProcessing: false,
      activeRequest: null,
      pendingApproval: null,
      scrollTop: 0,
      stickToBottom: true,
      collapsedThinkingEntryIds: [],
    }));
  }, [updateWorkspaceTerminal]);

  const setWorkspaceSession = useCallback((id: string, chatSessionId?: string) => {
    // Session ids are scoped per workspace so each tab can maintain an independent conversation.
    updateWorkspaceTerminal(id, (terminal) => ({ ...terminal, chatSessionId }));
  }, [updateWorkspaceTerminal]);

  const setWorkspaceInputDraft = useCallback((id: string, inputDraft: string) => {
    updateWorkspaceTerminal(id, (terminal) => ({ ...terminal, inputDraft }));
  }, [updateWorkspaceTerminal]);

  const setWorkspaceProcessing = useCallback((id: string, isProcessing: boolean) => {
    updateWorkspaceTerminal(id, (terminal) => ({ ...terminal, isProcessing }));
  }, [updateWorkspaceTerminal]);

  const setWorkspaceActiveRequest = useCallback(
    (id: string, activeRequest: TerminalRequestState | null) => {
      updateWorkspaceTerminal(id, (terminal) => ({ ...terminal, activeRequest }));
    },
    [updateWorkspaceTerminal],
  );

  const setWorkspacePendingApproval = useCallback(
    (id: string, pendingApproval: PendingAgentApproval | null) => {
      updateWorkspaceTerminal(id, (terminal) => ({ ...terminal, pendingApproval }));
    },
    [updateWorkspaceTerminal],
  );

  const setWorkspaceScrollState = useCallback(
    (
      id: string,
      scrollState: Pick<WorkspaceTerminalState, 'scrollTop' | 'stickToBottom'>,
    ) => {
      updateWorkspaceTerminal(id, (terminal) => ({
        ...terminal,
        scrollTop: scrollState.scrollTop,
        stickToBottom: scrollState.stickToBottom,
      }));
    },
    [updateWorkspaceTerminal],
  );

  const toggleWorkspaceThinkingCollapse = useCallback(
    (id: string, entryId: string) => {
      updateWorkspaceTerminal(id, (terminal) => {
        const collapsedThinkingEntryIds = terminal.collapsedThinkingEntryIds.includes(entryId)
          ? terminal.collapsedThinkingEntryIds.filter((currentId) => currentId !== entryId)
          : [...terminal.collapsedThinkingEntryIds, entryId];

        return {
          ...terminal,
          collapsedThinkingEntryIds,
        };
      });
    },
    [updateWorkspaceTerminal],
  );

  const renameWorkspace = useCallback((id: string, name: string) => {
    setWorkspaces(prev =>
      prev.map(w =>
        w.id === id ? { ...w, name } : w
      )
    );
  }, []);

  const setPortfolioName = useCallback((id: string, portfolioName: string | null) => {
    setWorkspaces(prev =>
      prev.map(w =>
        w.id === id ? { ...w, portfolioName } : w
      )
    );
  }, []);

  const restoreWorkspaceTranscript = useCallback(
    (workspaceId: string, transcript: TerminalEntry[], chatSessionId?: string) => {
      updateWorkspaceTerminal(workspaceId, (terminal) => ({
        ...terminal,
        history: transcript,
        chatSessionId: chatSessionId ?? undefined,
        inputDraft: '',
        isProcessing: false,
        activeRequest: null,
        pendingApproval: null,
        scrollTop: 0,
        stickToBottom: true,
        collapsedThinkingEntryIds: [],
      }));
    },
    [updateWorkspaceTerminal],
  );

  return {
    workspaces,
    activeWorkspace,
    activeWorkspaceId,
    createWorkspace,
    closeWorkspace,
    setActiveWorkspace,
    updateWorkspaceHistory,
    appendWorkspaceEntry,
    updateWorkspaceEntry,
    clearWorkspace,
    setWorkspaceSession,
    setWorkspaceInputDraft,
    setWorkspaceProcessing,
    setWorkspaceActiveRequest,
    setWorkspacePendingApproval,
    setWorkspaceScrollState,
    toggleWorkspaceThinkingCollapse,
    updateWorkspaceTerminal,
    renameWorkspace,
    setPortfolioName,
    restoreWorkspaceTranscript,
  };
};
