/**
 * Wallet State Screen - Displays wallet balances and history.
 * 
 * Shows:
 * - Total balance
 * - Wallet history (invitations, reservations)
 * - Navigation to other actions
 */

import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { Box, Text, useInput } from 'ink';
import { ScrollableList, type ListItemData } from '../components/List.js';
import { useNavigation } from '../hooks/useNavigation.js';
import { useAppContext, useStatus } from '../hooks/useAppContext.js';
import { colors, formatSatoshis, formatHex, logoSmall } from '../theme.js';
import type { HistoryItem } from '../../services/history.js';

// Import utility functions
import {
  formatHistoryListItem,
  getHistoryItemColorName,
  formatHistoryDate,
  type HistoryColorName,
} from '../../utils/history-utils.js';

/**
 * Map history color name to theme color.
 */
function getHistoryColor(colorName: HistoryColorName): string {
  switch (colorName) {
    case 'info':
      return colors.info as string;
    case 'warning':
      return colors.warning as string;
    case 'success':
      return colors.success as string;
    case 'error':
      return colors.error as string;
    case 'muted':
      return colors.textMuted as string;
    case 'text':
    default:
      return colors.text as string;
  }
}

/**
 * Menu action items.
 */
const menuItems: ListItemData<string>[] = [
  { key: 'new-tx', label: 'New Transaction (from template)', value: 'new-tx' },
  { key: 'import', label: 'Import Invitation', value: 'import' },
  { key: 'invitations', label: 'View Invitations', value: 'invitations' },
  { key: 'new-address', label: 'Generate New Address', value: 'new-address' },
  { key: 'refresh', label: 'Refresh', value: 'refresh' },
];

/**
 * History list item with HistoryItem value.
 */
type HistoryListItem = ListItemData<HistoryItem>;

/**
 * Wallet State Screen Component.
 * Displays wallet balance, history, and action menu.
 */
export function WalletStateScreen(): React.ReactElement {
  const { navigate } = useNavigation();
  const { appService, showError, showInfo } = useAppContext();
  const { setStatus } = useStatus();

  // State
  const [balance, setBalance] = useState<{ totalSatoshis: bigint; utxoCount: number } | null>(null);
  const [history, setHistory] = useState<HistoryItem[]>([]);
  const [focusedPanel, setFocusedPanel] = useState<'menu' | 'history'>('menu');
  const [selectedMenuIndex, setSelectedMenuIndex] = useState(0);
  const [selectedHistoryIndex, setSelectedHistoryIndex] = useState(0);
  const [isLoading, setIsLoading] = useState(true);

  /**
   * Refreshes wallet state.
   */
  const refresh = useCallback(async () => {
    if (!appService) {
      showError('AppService not initialized');
      return;
    }

    try {
      setIsLoading(true);
      setStatus('Loading wallet state...');

      // Get UTXOs for balance calculation
      const utxoData = await appService.engine.listUnspentOutputsData();

      // Calculate balance
      const selectableUtxos = utxoData.filter(utxo => utxo.selectable);
      const balanceData = selectableUtxos.reduce((acc, utxo) => acc + BigInt(utxo.valueSatoshis), BigInt(0));
      setBalance({
        totalSatoshis: balanceData,
        utxoCount: selectableUtxos.length,  
      });

      // Get wallet history from the history service
      const historyData = await appService.history.getHistory();
      setHistory(historyData);

      setStatus('Wallet ready');
      setIsLoading(false);
    } catch (error) {
      showError(`Failed to load wallet state: ${error instanceof Error ? error.message : String(error)}`);
      setIsLoading(false);
    }
  }, [appService, setStatus, showError]);

  // Load wallet state on mount
  useEffect(() => {
    refresh();
  }, [refresh]);

  /**
   * Generates a new receiving address.
   */
  const generateNewAddress = useCallback(async () => {
    if (!appService) {
      showError('AppService not initialized');
      return;
    }

    try {
      setStatus('Generating new address...');

      // Get the default P2PKH template
      const templates = await appService.engine.listImportedTemplates();
      const p2pkhTemplate = templates.find(t => t.name?.includes('P2PKH'));

      if (!p2pkhTemplate) {
        showError('P2PKH template not found');
        return;
      }

      // Generate a new locking bytecode
      const { generateTemplateIdentifier } = await import('@xo-cash/engine');
      const templateId = generateTemplateIdentifier(p2pkhTemplate);

      const lockingBytecode = await appService.engine.generateLockingBytecode(
        templateId,
        'receiveOutput',
        'receiver',
      );

      showInfo(`New address generated!\n\nLocking bytecode:\n${formatHex(lockingBytecode, 40)}`);

      // Refresh to show updated state
      await refresh();
    } catch (error) {
      showError(`Failed to generate address: ${error instanceof Error ? error.message : String(error)}`);
    }
  }, [appService, setStatus, showInfo, showError, refresh]);

  /**
   * Handles menu action.
   */
  const handleMenuAction = useCallback((action: string) => {
    switch (action) {
      case 'new-tx':
        navigate('templates');
        break;
      case 'import':
        navigate('invitations', { mode: 'import' });
        break;
      case 'invitations':
        navigate('invitations', { mode: 'list' });
        break;
      case 'new-address':
        generateNewAddress();
        break;
      case 'refresh':
        refresh();
        break;
    }
  }, [navigate, generateNewAddress, refresh]);

  /**
   * Handle menu item activation.
   */
  const handleMenuItemActivate = useCallback((item: ListItemData<string>, index: number) => {
    if (item.value) {
      handleMenuAction(item.value);
    }
  }, [handleMenuAction]);

  /**
   * Build history list items for ScrollableList.
   */
  const historyListItems = useMemo((): HistoryListItem[] => {
    return history.map(item => {
      const formatted = formatHistoryListItem(item, false);
      return {
        key: item.id,
        label: formatted.label,
        description: formatted.description,
        value: item,
        color: formatted.color,
        hidden: !formatted.isValid,
      };
    });
  }, [history]);

  // Handle keyboard navigation between panels
  useInput((input, key) => {
    if (key.tab) {
      setFocusedPanel(prev => prev === 'menu' ? 'history' : 'menu');
    }
  });

  /**
   * Render custom history list item.
   */
  const renderHistoryItem = useCallback((
    item: HistoryListItem,
    isSelected: boolean,
    isFocused: boolean
  ): React.ReactNode => {
    const historyItem = item.value;
    if (!historyItem) return null;

    const colorName = getHistoryItemColorName(historyItem.type, isFocused);
    const itemColor = isFocused ? colors.focus : getHistoryColor(colorName);
    const dateStr = formatHistoryDate(historyItem.timestamp);
    const indicator = isFocused ? '▸ ' : '  ';

    // Format based on type
    if (historyItem.type === 'invitation_created') {
      return (
        <Box flexDirection="row" justifyContent="space-between">
          <Text color={itemColor}>
            {indicator}[Invitation] {historyItem.description}
          </Text>
          {dateStr && <Text color={colors.textMuted}>{dateStr}</Text>}
        </Box>
      );
    } else if (historyItem.type === 'utxo_reserved') {
      const sats = historyItem.valueSatoshis ?? 0n;
      return (
        <Box flexDirection="row" justifyContent="space-between">
          <Box>
            <Text color={itemColor}>
              {indicator}[Reserved] {formatSatoshis(sats)}
            </Text>
            <Text color={colors.textMuted}> {historyItem.description}</Text>
          </Box>
          {dateStr && <Text color={colors.textMuted}>{dateStr}</Text>}
        </Box>
      );
    } else if (historyItem.type === 'utxo_received') {
      const sats = historyItem.valueSatoshis ?? 0n;
      const reservedTag = historyItem.reserved ? ' [Reserved]' : '';
      return (
        <Box flexDirection="row" justifyContent="space-between">
          <Box flexDirection="row">
            <Text color={itemColor}>
              {indicator}{formatSatoshis(sats)}
            </Text>
            <Text color={colors.textMuted}>
              {' '}{historyItem.description}{reservedTag}
            </Text>
          </Box>
          {dateStr && <Text color={colors.textMuted}>{dateStr}</Text>}
        </Box>
      );
    }

    // Fallback for other types
    return (
      <Box flexDirection="row" justifyContent="space-between">
        <Text color={itemColor}>
          {indicator}{historyItem.type}: {historyItem.description}
        </Text>
        {dateStr && <Text color={colors.textMuted}>{dateStr}</Text>}
      </Box>
    );
  }, []);

  return (
    <Box flexDirection="column" flexGrow={1}>
      {/* Header */}
      <Box borderStyle="single" borderColor={colors.secondary} paddingX={1}>
        <Text color={colors.primary} bold>{logoSmall} - Wallet Overview</Text>
      </Box>

      {/* Main content */}
      <Box flexDirection="row" marginTop={1} flexGrow={1}>
        {/* Left column: Balance */}
        <Box 
          flexDirection="column" 
          width="50%" 
          paddingRight={1}
        >
          <Box
            borderStyle="single"
            borderColor={colors.primary}
            flexDirection="column"
            paddingX={1}
            paddingY={1}
          >
            <Text color={colors.primary} bold> Balance </Text>
            <Box marginTop={1} flexDirection="column">
              <Text color={colors.text}>Total Balance:</Text>
              {balance ? (
                <>
                  <Text color={colors.success} bold>
                    {formatSatoshis(balance.totalSatoshis)}
                  </Text>
                  <Text color={colors.textMuted}>
                    UTXOs: {balance.utxoCount}
                  </Text>
                </>
              ) : (
                <Text color={colors.textMuted}>Loading...</Text>
              )}
            </Box>
          </Box>
        </Box>

        {/* Right column: Actions menu */}
        <Box 
          flexDirection="column" 
          width="50%" 
          paddingLeft={1}
        >
          <Box
            borderStyle="single"
            borderColor={focusedPanel === 'menu' ? colors.focus : colors.border}
            flexDirection="column"
            paddingX={1}
          >
            <Text color={colors.primary} bold> Actions </Text>
            <ScrollableList
              items={menuItems}
              selectedIndex={selectedMenuIndex}
              onSelect={setSelectedMenuIndex}
              onActivate={handleMenuItemActivate}
              focus={focusedPanel === 'menu'}
              emptyMessage="No actions"
            />
          </Box>
        </Box>
      </Box>

      {/* Wallet History */}
      <Box marginTop={1} flexGrow={1}>
        <Box
          borderStyle="single"
          borderColor={focusedPanel === 'history' ? colors.focus : colors.border}
          flexDirection="column"
          paddingX={1}
          width="100%"
          height={14}
          overflow="hidden"
        >
          <Text color={colors.primary} bold> Wallet History {history.length > 0 ? `(${selectedHistoryIndex + 1}/${history.length})` : ''}</Text>
          {isLoading ? (
            <Box marginTop={1}>
              <Text color={colors.textMuted}>Loading...</Text>
            </Box>
          ) : (
            <ScrollableList
              items={historyListItems}
              selectedIndex={selectedHistoryIndex}
              onSelect={setSelectedHistoryIndex}
              focus={focusedPanel === 'history'}
              maxVisible={10}
              emptyMessage="No history found"
              renderItem={renderHistoryItem}
            />
          )}
        </Box>
      </Box>

      {/* Help text */}
      <Box marginTop={1}>
        <Text color={colors.textMuted} dimColor>
          Tab: Switch focus • Enter: Select • ↑↓: Navigate • Esc: Back
        </Text>
      </Box>
    </Box>
  );
}
