import React, { useCallback, useEffect, useRef } from 'react';
import { Sidebar } from './components/Sidebar/Sidebar';
import { ConfirmDialog } from './components/Settings/ConfirmDialog';
import { TabBar } from './components/TabBar/TabBar';
import { Terminal } from './components/Terminal/Terminal';
import { useAppShortcuts } from './hooks/useAppShortcuts';
import { usePortfolioWorkflow } from './hooks/usePortfolioWorkflow';
import { useResearchCaptureFlow } from './hooks/useResearchCaptureFlow';
import type { ResearchComposerState } from './hooks/useResearchComposer';
import { useResearchWorkspaces } from './hooks/useResearchWorkspaces';
import { useTabs } from './hooks/useTabs';
import { useTerminalOrchestrator } from './hooks/useTerminalOrchestrator';
import { useTickerHistory } from './hooks/useTickerHistory';
import { agentSettingsBridge } from './lib/agentSettingsBridge';
import { terminalBridge } from './lib/terminalBridge';
import { AgentConfigStatus } from './types/agentSettings';
import {
  NoteCaptureResult,
  ResearchNavigationIntent,
} from './types/research';
import './App.css';

// Error Boundary Component for catching React rendering errors
class SettingsErrorBoundary extends React.Component<
  { children: React.ReactNode },
  { hasError: boolean; error: Error | null }
> {
  constructor(props: { children: React.ReactNode }) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error('SettingsPage Error Boundary caught an error:', error);
    console.error('Error Info:', errorInfo);
    console.error('Component Stack:', errorInfo.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="flex h-screen w-screen items-center justify-center bg-term-bg text-term-text">
          <div className="max-w-2xl rounded-lg border border-term-border bg-term-surface p-8 shadow-lg">
            <h1 className="mb-4 text-2xl font-mono font-semibold text-negative">
              Settings Page Error
            </h1>
            <p className="mb-4 font-mono text-term-text-muted">
              The settings page encountered an unexpected error. Please check the
              browser console for details.
            </p>
            {this.state.error && (
              <details className="mb-4">
                <summary className="cursor-pointer font-mono text-sm text-term-text-muted hover:text-term-text">
                  Error details
                </summary>
                <pre className="mt-2 overflow-auto rounded bg-term-bg p-4 text-xs font-mono text-negative">
                  {this.state.error.toString()}
                  {this.state.error.stack}
                </pre>
              </details>
            )}
            <button
              type="button"
              onClick={() => window.location.reload()}
              className="rounded border border-info bg-term-highlight px-4 py-2 font-mono text-sm text-info transition-colors hover:brightness-110"
            >
              Reload Application
            </button>
          </div>
        </div>
      );
    }

    return this.props.children;
  }
}

type AppView = 'terminal' | 'research' | 'settings';

const ResearchMode = React.lazy(() =>
  import('./components/Research/ResearchMode').then((module) => ({
    default: module.ResearchMode,
  })),
);

const SettingsPage = React.lazy(() =>
  import('./components/Settings/SettingsPage').then((module) => ({
    default: module.SettingsPage,
  })),
);

function App() {
  const tabs = useTabs();
  const tickerHistory = useTickerHistory();
  const portfolioWorkflow = usePortfolioWorkflow();
  const [activeView, setActiveView] = React.useState<AppView>('terminal');
  const [researchIntent, setResearchIntent] = React.useState<ResearchNavigationIntent | null>(null);
  const [agentStatus, setAgentStatus] = React.useState<AgentConfigStatus | null>(null);
  const [sidebarOpen, setSidebarOpen] = React.useState(true);
  const outputRef = useRef<HTMLDivElement | null>(null);
  const hasAutoLoadedPortfolioRef = useRef(false);
  const activePortfolioWorkflow = portfolioWorkflow.readWorkflow(tabs.activeWorkspaceId);
  const researchWorkspaces = useResearchWorkspaces();
  const { captureNote: captureResearchNote } = useResearchCaptureFlow({
    ensureWorkspace: researchWorkspaces.ensureWorkspace,
  });

  const refreshAgentStatus = useCallback(async () => {
    const status = await agentSettingsBridge.getStatus();
    setAgentStatus(status);
    return status;
  }, []);

  const handleAgentStatusChange = useCallback((status: AgentConfigStatus) => {
    setAgentStatus(status);
  }, []);

  const handleOpenSettings = useCallback(async () => {
    try {
      await refreshAgentStatus();
    } finally {
      portfolioWorkflow.exitPortfolioMode(tabs.activeWorkspaceId);
      setActiveView('settings');
    }
  }, [portfolioWorkflow, refreshAgentStatus, tabs.activeWorkspaceId]);

  const handleReturnToTerminal = useCallback(() => {
    setActiveView('terminal');
  }, []);

  const handleEnsureResearchWorkspace = useCallback(
    (request: { ticker?: string; workspaceId?: string | null }) =>
      researchWorkspaces.ensureWorkspace(request),
    [researchWorkspaces],
  );

  const handleCaptureResearchNote = useCallback(
    async (args: {
      draft: ResearchComposerState;
      fallbackTicker?: string;
      explicitWorkspaceId?: string | null;
      autoCreateFromTicker?: boolean;
    }): Promise<NoteCaptureResult> => {
      const result = await captureResearchNote(args);
      researchWorkspaces.selectWorkspace(result.note.workspaceId);
      return result;
    },
    [captureResearchNote, researchWorkspaces],
  );

  const handleOpenResearch = useCallback(
    async (intent: ResearchNavigationIntent = {}) => {
      const workspace = await researchWorkspaces.ensureWorkspaceForIntent(intent);
      if (workspace) {
        researchWorkspaces.selectWorkspace(workspace.id);
      }
      setResearchIntent(intent);
      setActiveView('research');
    },
    [researchWorkspaces],
  );

  const {
    commandInputRef,
    clearWorkspaceSession,
    handleClearPortfolioAction,
    handleCommand,
    handleStartPortfolioAction,
    handleUpdatePortfolioDraft,
    isProcessing,
    pendingAgentApproval,
    resetCommandIndex,
    resolvePendingAgentApproval,
    runCommand,
  } = useTerminalOrchestrator({
    tabs,
    tickerHistory,
    portfolioWorkflow,
    setActiveView,
  });

  const clearTerminal = useCallback(() => {
    setActiveView('terminal');
    clearWorkspaceSession(tabs.activeWorkspaceId);
  }, [clearWorkspaceSession, tabs.activeWorkspaceId]);

  const handleCreateWorkspace = useCallback(() => {
    setActiveView('terminal');
    tabs.createWorkspace();
  }, [tabs]);

  useAppShortcuts({
    activeView,
    activeWorkspaceId: tabs.activeWorkspaceId,
    commandInputRef,
    isProcessing,
    onClearTerminal: clearTerminal,
    onCloseWorkspace: tabs.closeWorkspace,
    onCreateWorkspace: handleCreateWorkspace,
    onOpenResearch: () => {
      void handleOpenResearch();
    },
    onOpenSettings: () => {
      void handleOpenSettings();
    },
    onToggleSidebar: () => setSidebarOpen((prev) => !prev),
  });

  useEffect(() => {
    let active = true;

    void refreshAgentStatus().catch(() => {
      if (active) {
        setAgentStatus(null);
      }
    });

    return () => {
      active = false;
    };
  }, [refreshAgentStatus]);

  useEffect(() => {
    return () => {
      void terminalBridge.dispose();
    };
  }, []);

  useEffect(() => {
    if (hasAutoLoadedPortfolioRef.current || activeView !== 'terminal' || isProcessing) {
      return;
    }

    hasAutoLoadedPortfolioRef.current = true;
    // Reset portfolio loading state before triggering command
    portfolioWorkflow.resetPortfolioLoading(tabs.activeWorkspaceId);
    void handleCommand('/portfolio');
  }, [activeView, handleCommand, isProcessing, portfolioWorkflow, tabs.activeWorkspaceId]);

  // Sync portfolio names from workflow to workspaces
  React.useEffect(() => {
    tabs.workspaces.forEach((workspace) => {
      const workflow = portfolioWorkflow.readWorkflow(workspace.id);
      if (workflow.portfolioName !== workspace.portfolioName) {
        tabs.setPortfolioName(workspace.id, workflow.portfolioName);
      }
    });
  }, [portfolioWorkflow, tabs.workspaces, tabs.setPortfolioName]);

  const tabBarTabs = tabs.workspaces.map((workspace) => {
    const workflow = portfolioWorkflow.readWorkflow(workspace.id);
    return {
      id: workspace.id,
      name: workspace.name,
      isActive: workspace.id === tabs.activeWorkspaceId,
      portfolioName: workflow.portfolioName,
    };
  });

  if (activeView === 'settings') {
    return (
      <div className="h-screen w-screen bg-term-bg text-term-text">
        <React.Suspense fallback={<div className="flex h-full items-start p-6 text-sm text-term-text-muted">Loading settings...</div>}>
          <SettingsErrorBoundary>
            <SettingsPage
              status={agentStatus}
              onRefreshStatus={refreshAgentStatus}
              onStatusChange={handleAgentStatusChange}
              onBackToTerminal={handleReturnToTerminal}
            />
          </SettingsErrorBoundary>
        </React.Suspense>

        <ConfirmDialog
          isOpen={pendingAgentApproval !== null}
          title={pendingAgentApproval?.title ?? 'Approve command'}
          message={pendingAgentApproval?.message ?? ''}
          confirmLabel="Approve"
          cancelLabel="Deny"
          variant="warning"
          onConfirm={() => resolvePendingAgentApproval(true)}
          onCancel={() => resolvePendingAgentApproval(false)}
        />
      </div>
    );
  }

  return (
    <div className="flex h-screen bg-term-bg text-term-text">
      {activeView === 'terminal' && (
        <Sidebar
          activeView={activeView}
          isOpen={sidebarOpen}
          onOpenResearch={() => {
            void handleOpenResearch();
          }}
          onOpenTerminal={() => setActiveView('terminal')}
          onOpenSettings={() => {
            void handleOpenSettings();
          }}
          onToggle={() => setSidebarOpen((prev) => !prev)}
          onCommand={handleCommand}
          portfolio={activePortfolioWorkflow.portfolioSnapshot}
          tickerHistory={tickerHistory.history}
          isTickerHistoryLoaded={tickerHistory.isLoaded}
        />
      )}

      <div
        className={`flex-1 ${sidebarOpen ? 'ml-0' : ''} transition-all flex min-h-0 min-w-0 flex-col`}
      >
        {activeView === 'terminal' ? (
          <TabBar
            tabs={tabBarTabs}
            onTabClick={(id) => {
              setActiveView('terminal');
              tabs.setActiveWorkspace(id);
            }}
            onTabClose={(id) => tabs.closeWorkspace(id)}
            onNewTab={handleCreateWorkspace}
            onTabRename={(id, name) => tabs.renameWorkspace(id, name)}
          />
        ) : null}

        {activeView === 'research' ? (
          <React.Suspense fallback={<div className="flex-1 p-6 text-sm text-term-text-muted">Loading research workspace...</div>}>
            <ResearchMode
              workspaces={researchWorkspaces.workspaces}
              activeWorkspaceId={researchWorkspaces.activeWorkspaceId}
              navigationIntent={researchIntent}
              onSelectWorkspace={researchWorkspaces.selectWorkspace}
              onEnsureWorkspace={handleEnsureResearchWorkspace}
              onCaptureResearchNote={handleCaptureResearchNote}
              onConsumeNavigationIntent={() => setResearchIntent(null)}
              onOpenTerminal={handleReturnToTerminal}
              onOpenSettings={handleOpenSettings}
              isSidebarOpen={sidebarOpen}
              onToggleSidebar={() => setSidebarOpen((prev) => !prev)}
              activeView={activeView}
            />
          </React.Suspense>
        ) : (
          <Terminal
            history={tabs.activeWorkspace?.history ?? []}
            isProcessing={isProcessing}
            outputRef={outputRef}
            inputRef={commandInputRef}
            onSubmit={handleCommand}
            onRunCommand={runCommand}
            onStartPortfolioAction={handleStartPortfolioAction}
            onUpdatePortfolioDraft={handleUpdatePortfolioDraft}
            onClearPortfolioAction={handleClearPortfolioAction}
            resetCommandIndex={resetCommandIndex}
            portfolioWorkflow={activePortfolioWorkflow}
            researchWorkspaces={researchWorkspaces.workspaces}
            activeResearchWorkspaceId={researchWorkspaces.activeWorkspaceId}
            onCaptureResearchNote={handleCaptureResearchNote}
          />
        )}
      </div>

      <ConfirmDialog
        isOpen={pendingAgentApproval !== null}
        title={pendingAgentApproval?.title ?? 'Approve command'}
        message={pendingAgentApproval?.message ?? ''}
        confirmLabel="Approve"
        cancelLabel="Deny"
        variant="warning"
        onConfirm={() => resolvePendingAgentApproval(true)}
        onCancel={() => resolvePendingAgentApproval(false)}
      />
    </div>
  );
}

export default App;
