import { useCallback, useState } from 'react';
import { Portfolio } from '../types/financial';
import {
  PortfolioAction,
  PortfolioActionDraft,
  PortfolioActionSeed,
  TerminalCommandResponse,
} from '../types/terminal';

export type PortfolioSnapshotStatus = 'idle' | 'loading' | 'ready' | 'error';

export interface PortfolioWorkflowState {
  isPortfolioMode: boolean;
  activePortfolioAction: PortfolioAction | null;
  portfolioSnapshot: Portfolio | null;
  portfolioSnapshotStatus: PortfolioSnapshotStatus;
  draft: PortfolioActionDraft;
  lastPortfolioCommand: string | null;
}

const EMPTY_DRAFT: PortfolioActionDraft = {
  symbol: '',
  quantity: '',
  price: '',
  amount: '',
};

const createDefaultState = (): PortfolioWorkflowState => ({
  isPortfolioMode: false,
  activePortfolioAction: null,
  portfolioSnapshot: null,
  portfolioSnapshotStatus: 'idle',
  draft: EMPTY_DRAFT,
  lastPortfolioCommand: null,
});

const mergeDraft = (
  draft: PortfolioActionDraft,
  seed?: PortfolioActionSeed,
): PortfolioActionDraft => ({
  symbol: seed?.symbol ?? draft.symbol,
  quantity: seed?.quantity ?? draft.quantity,
  price: seed?.price ?? draft.price,
  amount: seed?.amount ?? draft.amount,
});

const commandToPortfolioAction = (command: string): PortfolioAction | null => {
  const normalized = command.trim().toLowerCase();

  if (normalized === '/portfolio') {
    return 'overview';
  }
  if (normalized === '/portfolio stats') {
    return 'stats';
  }
  if (normalized.startsWith('/portfolio history')) {
    return 'history';
  }
  if (normalized.startsWith('/buy ')) {
    return 'buy';
  }
  if (normalized.startsWith('/sell ')) {
    return 'sell';
  }
  if (normalized.startsWith('/cash deposit')) {
    return 'deposit';
  }
  if (normalized.startsWith('/cash withdraw')) {
    return 'withdraw';
  }

  return null;
};

export const isPortfolioCommand = (command: string): boolean =>
  commandToPortfolioAction(command) !== null;

export const usePortfolioWorkflow = () => {
  const [workflows, setWorkflows] = useState<Record<string, PortfolioWorkflowState>>({});

  const readWorkflow = useCallback(
    (workspaceId: string): PortfolioWorkflowState =>
      workflows[workspaceId] ?? createDefaultState(),
    [workflows],
  );

  const updateWorkflow = useCallback(
    (
      workspaceId: string,
      updater: (current: PortfolioWorkflowState) => PortfolioWorkflowState,
    ) => {
      setWorkflows((current) => {
        const nextCurrent = current[workspaceId] ?? createDefaultState();
        return {
          ...current,
          [workspaceId]: updater(nextCurrent),
        };
      });
    },
    [],
  );

  const noteCommandStart = useCallback(
    (workspaceId: string, command: string) => {
      const action = commandToPortfolioAction(command);
      if (!action) {
        return;
      }

      updateWorkflow(workspaceId, (current) => ({
        ...current,
        isPortfolioMode: true,
        activePortfolioAction: action,
        lastPortfolioCommand: command,
        portfolioSnapshotStatus:
          action === 'overview' ? 'loading' : current.portfolioSnapshotStatus,
      }));
    },
    [updateWorkflow],
  );

  const noteCommandResponse = useCallback(
    (
      workspaceId: string,
      command: string,
      response: TerminalCommandResponse,
    ) => {
      const action = commandToPortfolioAction(command);
      if (!action) {
        return;
      }

      const latestPortfolioSnapshot =
        response.kind === 'panel' && response.panel.type === 'portfolio'
          ? response.panel.data
          : response.kind === 'text'
            ? response.portfolio ?? null
            : null;

      updateWorkflow(workspaceId, (current) => {
        if (response.kind === 'panel' && response.panel.type === 'portfolio') {
          return {
            ...current,
            isPortfolioMode: true,
            activePortfolioAction: 'overview',
            portfolioSnapshot: latestPortfolioSnapshot,
            portfolioSnapshotStatus: 'ready',
            lastPortfolioCommand: command,
          };
        }

        const completedTradeAction =
          action === 'buy' ||
          action === 'sell' ||
          action === 'deposit' ||
          action === 'withdraw';

        return {
          ...current,
          isPortfolioMode: true,
          activePortfolioAction: completedTradeAction ? null : action,
          portfolioSnapshot: latestPortfolioSnapshot ?? current.portfolioSnapshot,
          portfolioSnapshotStatus: latestPortfolioSnapshot
            ? 'ready'
            : current.portfolioSnapshotStatus,
          lastPortfolioCommand: command,
        };
      });
    },
    [updateWorkflow],
  );

  const noteCommandError = useCallback(
    (workspaceId: string, command: string) => {
      const action = commandToPortfolioAction(command);
      if (!action) {
        return;
      }

      updateWorkflow(workspaceId, (current) => ({
        ...current,
        isPortfolioMode: true,
        activePortfolioAction: action,
        portfolioSnapshotStatus:
          action === 'overview' ? 'error' : current.portfolioSnapshotStatus,
        lastPortfolioCommand: command,
      }));
    },
    [updateWorkflow],
  );

  const startPortfolioAction = useCallback(
    (workspaceId: string, action: PortfolioAction, seed?: PortfolioActionSeed) => {
      updateWorkflow(workspaceId, (current) => ({
        ...current,
        isPortfolioMode: true,
        activePortfolioAction: action,
        draft: mergeDraft(
          {
            ...EMPTY_DRAFT,
            ...(action === 'buy' || action === 'sell'
              ? { symbol: current.draft.symbol }
              : {}),
          },
          seed,
        ),
      }));
    },
    [updateWorkflow],
  );

  const clearPortfolioAction = useCallback(
    (workspaceId: string) => {
      updateWorkflow(workspaceId, (current) => ({
        ...current,
        activePortfolioAction: null,
        draft: EMPTY_DRAFT,
      }));
    },
    [updateWorkflow],
  );

  const updateDraft = useCallback(
    (workspaceId: string, patch: Partial<PortfolioActionDraft>) => {
      updateWorkflow(workspaceId, (current) => ({
        ...current,
        draft: {
          ...current.draft,
          ...patch,
        },
      }));
    },
    [updateWorkflow],
  );

  const exitPortfolioMode = useCallback(
    (workspaceId: string) => {
      updateWorkflow(workspaceId, (current) => ({
        ...current,
        isPortfolioMode: false,
        activePortfolioAction: null,
        draft: EMPTY_DRAFT,
      }));
    },
    [updateWorkflow],
  );

  return {
    readWorkflow,
    noteCommandStart,
    noteCommandResponse,
    noteCommandError,
    startPortfolioAction,
    clearPortfolioAction,
    updateDraft,
    exitPortfolioMode,
  };
};
