/**
 * Main App component for the XO Wallet CLI.
 * Uses Ink for terminal rendering with React components.
 */

import React from 'react';
import { Box, Text, useApp, useInput } from 'ink';
import { NavigationProvider, useNavigation } from './hooks/useNavigation.js';
import { AppProvider, useAppContext, useDialog, useStatus } from './hooks/useAppContext.js';
import type { AppConfig } from '../app.js';
import { colors, logoSmall } from './theme.js';

// Screen imports
import { SeedInputScreen } from './screens/SeedInput.js';
import { WalletStateScreen } from './screens/WalletState.js';
import { TemplateListScreen } from './screens/TemplateList.js';
import { ActionWizardScreen } from './screens/action-wizard/ActionWizardScreen.js';
import { InvitationScreen } from './screens/invitations/InvitationScreen.js';
import { TransactionScreen } from './screens/Transaction.js';

import { MessageDialog } from './components/Dialog.js';

/**
 * Props for the App component.
 */
interface AppProps {
  config: AppConfig;
}

/**
 * Router component that renders the current screen.
 */
function Router(): React.ReactElement {
  const { screen } = useNavigation();

  switch (screen) {
    case 'seed-input':
      return <SeedInputScreen />;
    case 'wallet':
      return <WalletStateScreen />;
    case 'templates':
      return <TemplateListScreen />;
    case 'wizard':
      return <ActionWizardScreen />;
    case 'invitations':
      return <InvitationScreen />;
    case 'transaction':
      return <TransactionScreen />;
    default:
      return <Text color={colors.error}>Unknown screen: {screen}</Text>;
  }
}

/**
 * Status bar component shown at the bottom of the screen.
 */
function StatusBar(): React.ReactElement {
  const { status } = useStatus();
  const { screen, canGoBack } = useNavigation();

  return (
    <Box 
      borderStyle="single" 
      borderColor={colors.border}
      paddingX={1}
      justifyContent="space-between"
    >
      <Text color={colors.primary} bold>{logoSmall}</Text>
      <Text color={colors.textMuted}>{status}</Text>
      <Text color={colors.textMuted}>
        {canGoBack ? 'ESC: Back | ' : ''}q: Quit
      </Text>
    </Box>
  );
}

/**
 * Dialog overlay component for modals.
 */
function DialogOverlay(): React.ReactElement | null {
  const { dialog, setDialog } = useDialog();

  // 'custom' dialogs are rendered and managed by the screen itself;
  // we only handle input for the built-in dialog types.
  const isBuiltInDialog = dialog?.visible === true && dialog.type !== 'custom';

  useInput((input, key) => {
    if (!isBuiltInDialog) return;

    if (key.return || input === 'y' || input === 'Y') {
      if (dialog.type === 'confirm' && dialog.onConfirm) {
        dialog.onConfirm();
      } else {
        dialog.onCancel?.();
      }
    } else if (key.escape || input === 'n' || input === 'N') {
      dialog.onCancel?.();
    }
  }, { isActive: isBuiltInDialog });

  if (!isBuiltInDialog) return null;

  const borderColor = dialog.type === 'error' ? colors.error : 
                      dialog.type === 'confirm' ? colors.warning : 
                      colors.info;

  return (
    <Box
      position="absolute"
      flexDirection="column"
      alignItems="center"
      justifyContent="center"
      width="100%"
      height="100%"
    >
      <MessageDialog
        title={dialog.type === 'error' ? '✗ Error' : 
          dialog.type === 'confirm' ? '? Confirm' : 
          'ℹ Info'}
        message={dialog.message}
        onClose={dialog.onCancel ?? (() => {})}
        type={dialog.type as 'error' | 'info' | 'success'}
      />
    </Box>
  );
}

/**
 * Main content wrapper with global keybindings.
 */
function MainContent(): React.ReactElement {
  const { exit } = useApp();
  const { goBack, canGoBack } = useNavigation();
  const { screen } = useNavigation();
  const { dialog } = useDialog();
  const appContext = useAppContext();

  // Global keybindings (disabled when dialog is shown)
  useInput((input, key) => {
    // Don't handle global keys when dialog is shown
    if (dialog?.visible) return;

    // Quit on 'q' or Ctrl+C
    if (
      // Commenting out 'q'. Its annoying me - It activates in text inputs.
      // input === 'q'
      (key.ctrl && input === 'c')
    ) {
      appContext.exit();
      exit();
    }

    // Go back on Escape
    if (key.escape && canGoBack) {
      goBack();

      // If we went back to the seed input screen, remove the current engine
      // TODO: This was to support going back to seed input then re-opening your seed, but there is a bug in the engine which prevents it from closing the current
      // storage instance, giving us an error about the database already being opened.
      if (screen === 'seed-input') {
        appContext.appService?.engine.stop();
        appContext.appService = null;
      }
    }
  });

  return (
    <Box flexDirection="column" height="100%">
      {/* Main content area */}
      <Box flexDirection="column" flexGrow={1}>
        <Router />
      </Box>
      
      {/* Status bar */}
      <StatusBar />
      
      {/* Dialog overlay */}
      <DialogOverlay />
    </Box>
  );
}

/**
 * Main App component.
 * Sets up providers and renders the main content.
 */
export function App({ config }: AppProps): React.ReactElement {
  const { exit } = useApp();

  // Cleanup will be handled by React when components unmount
  const handleExit = () => {
    exit();
  };

  return (
    <AppProvider
      config={config}
      onExit={handleExit}
    >
      <NavigationProvider initialScreen="seed-input">
        <MainContent />
      </NavigationProvider>
    </AppProvider>
  );
}
