/**
 * Action Wizard Screen - Step-by-step walkthrough for template actions.
 * 
 * Guides users through:
 * - Reviewing action requirements
 * - Entering variables (e.g., requestedSatoshis)
 * - Selecting inputs (UTXOs) for funding
 * - Reviewing outputs and change
 * - Creating and publishing invitation
 */

import React, { useState, useEffect, useCallback } from 'react';
import { Box, Text, useInput } from 'ink';
import TextInput from 'ink-text-input';
import { StepIndicator, type Step } from '../components/ProgressBar.js';
import { Button } from '../components/Button.js';
import { useNavigation } from '../hooks/useNavigation.js';
import { useAppContext, useStatus } from '../hooks/useAppContext.js';
import { colors, logoSmall, formatSatoshis, formatHex } from '../theme.js';
import { copyToClipboard } from '../utils/clipboard.js';
import type { XOTemplate, XOInvitation } from '@xo-cash/types';

/**
 * Wizard step types.
 */
type StepType = 'info' | 'variables' | 'inputs' | 'review' | 'publish';

/**
 * Wizard step definition.
 */
interface WizardStep {
  name: string;
  type: StepType;
}

/**
 * Variable input state.
 */
interface VariableInput {
  id: string;
  name: string;
  type: string;
  hint?: string;
  value: string;
}

/**
 * UTXO for selection.
 */
interface SelectableUTXO {
  outpointTransactionHash: string;
  outpointIndex: number;
  valueSatoshis: bigint;
  lockingBytecode?: string;
  selected: boolean;
}

/**
 * Action Wizard Screen Component.
 */
export function ActionWizardScreen(): React.ReactElement {
  const { navigate, goBack, data: navData } = useNavigation();
  const { walletController, invitationController, showError, showInfo } = useAppContext();
  const { setStatus } = useStatus();

  // Extract navigation data
  const templateIdentifier = navData.templateIdentifier as string | undefined;
  const actionIdentifier = navData.actionIdentifier as string | undefined;
  const roleIdentifier = navData.roleIdentifier as string | undefined;
  const template = navData.template as XOTemplate | undefined;

  // Wizard state
  const [steps, setSteps] = useState<WizardStep[]>([]);
  const [currentStep, setCurrentStep] = useState(0);
  
  // Variable inputs
  const [variables, setVariables] = useState<VariableInput[]>([]);
  
  // UTXO selection
  const [availableUtxos, setAvailableUtxos] = useState<SelectableUTXO[]>([]);
  const [selectedUtxoIndex, setSelectedUtxoIndex] = useState(0);
  const [requiredAmount, setRequiredAmount] = useState<bigint>(0n);
  const [fee, setFee] = useState<bigint>(500n); // Default fee estimate
  
  // Invitation state
  const [invitation, setInvitation] = useState<XOInvitation | null>(null);
  const [invitationId, setInvitationId] = useState<string | null>(null);
  
  // UI state
  const [focusedInput, setFocusedInput] = useState(0);
  const [focusedButton, setFocusedButton] = useState<'back' | 'cancel' | 'next'>('next');
  const [focusArea, setFocusArea] = useState<'content' | 'buttons'>('content');
  const [isProcessing, setIsProcessing] = useState(false);

  /**
   * Initialize wizard on mount.
   */
  useEffect(() => {
    if (!template || !actionIdentifier || !roleIdentifier) {
      showError('Missing wizard data');
      goBack();
      return;
    }

    // Build steps based on template
    const action = template.actions?.[actionIdentifier];
    const role = action?.roles?.[roleIdentifier];
    const requirements = role?.requirements;

    const wizardSteps: WizardStep[] = [
      { name: 'Welcome', type: 'info' },
    ];

    // Add variables step if needed
    if (requirements?.variables && requirements.variables.length > 0) {
      wizardSteps.push({ name: 'Variables', type: 'variables' });

      // Initialize variable inputs
      const varInputs = requirements.variables.map(varId => {
        const varDef = template.variables?.[varId];
        return {
          id: varId,
          name: varDef?.name || varId,
          type: varDef?.type || 'string',
          hint: varDef?.hint,
          value: '',
        };
      });
      setVariables(varInputs);
    }

    // Add inputs step if role requires slots (funding inputs)
    // Slots indicate the role needs to provide transaction inputs/outputs
    if (requirements?.slots && requirements.slots.min > 0) {
      wizardSteps.push({ name: 'Select UTXOs', type: 'inputs' });
    }

    wizardSteps.push({ name: 'Review', type: 'review' });
    wizardSteps.push({ name: 'Publish', type: 'publish' });

    setSteps(wizardSteps);
    setStatus(`${actionIdentifier}/${roleIdentifier}`);
  }, [template, actionIdentifier, roleIdentifier, showError, goBack, setStatus]);

  /**
   * Get current step data.
   */
  const currentStepData = steps[currentStep];

  /**
   * Calculate selected amount.
   */
  const selectedAmount = availableUtxos
    .filter(u => u.selected)
    .reduce((sum, u) => sum + u.valueSatoshis, 0n);

  /**
   * Calculate change amount.
   */
  const changeAmount = selectedAmount - requiredAmount - fee;

  /**
   * Load available UTXOs for the inputs step.
   */
  const loadAvailableUtxos = useCallback(async () => {
    if (!invitation || !templateIdentifier) return;

    try {
      setIsProcessing(true);
      setStatus('Finding suitable UTXOs...');

      // First, get the required amount from variables (e.g., requestedSatoshis)
      const requestedVar = variables.find(v => 
        v.id.toLowerCase().includes('satoshi') || 
        v.id.toLowerCase().includes('amount')
      );
      const requested = requestedVar ? BigInt(requestedVar.value || '0') : 0n;
      setRequiredAmount(requested);

      // Find suitable resources
      const resources = await walletController.findSuitableResources(invitation, {
        templateIdentifier,
        outputIdentifier: 'receiveOutput', // Common output identifier
      });

      // Convert to selectable UTXOs
      const utxos: SelectableUTXO[] = (resources.unspentOutputs || []).map((utxo: any) => ({
        outpointTransactionHash: utxo.outpointTransactionHash,
        outpointIndex: utxo.outpointIndex,
        valueSatoshis: BigInt(utxo.valueSatoshis),
        lockingBytecode: utxo.lockingBytecode 
          ? typeof utxo.lockingBytecode === 'string'
            ? utxo.lockingBytecode
            : Buffer.from(utxo.lockingBytecode).toString('hex')
          : undefined,
        selected: false,
      }));

      // Auto-select UTXOs to cover required amount + fee
      let accumulated = 0n;
      const seenLockingBytecodes = new Set<string>();
      
      for (const utxo of utxos) {
        // Ensure lockingBytecode uniqueness
        if (utxo.lockingBytecode && seenLockingBytecodes.has(utxo.lockingBytecode)) {
          continue;
        }
        if (utxo.lockingBytecode) {
          seenLockingBytecodes.add(utxo.lockingBytecode);
        }

        utxo.selected = true;
        accumulated += utxo.valueSatoshis;
        
        if (accumulated >= requested + fee) {
          break;
        }
      }

      setAvailableUtxos(utxos);
      setStatus('Ready');
    } catch (error) {
      showError(`Failed to load UTXOs: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setIsProcessing(false);
    }
  }, [invitation, templateIdentifier, variables, walletController, showError, setStatus]);

  /**
   * Toggle UTXO selection.
   */
  const toggleUtxoSelection = useCallback((index: number) => {
    setAvailableUtxos(prev => {
      const updated = [...prev];
      const utxo = updated[index];
      if (utxo) {
        updated[index] = { ...utxo, selected: !utxo.selected };
      }
      return updated;
    });
  }, []);

  /**
   * Navigate to next step.
   */
  const nextStep = useCallback(async () => {
    if (currentStep >= steps.length - 1) return;

    const stepType = currentStepData?.type;

    // Handle step-specific logic
    if (stepType === 'variables') {
      // Create invitation and add variables
      await createInvitationWithVariables();
      return;
    }

    if (stepType === 'inputs') {
      // Add selected inputs and outputs to invitation
      await addInputsAndOutputs();
      return;
    }

    if (stepType === 'review') {
      // Publish invitation
      await publishInvitation();
      return;
    }

    setCurrentStep(prev => prev + 1);
    setFocusArea('content');
    setFocusedInput(0);
  }, [currentStep, steps.length, currentStepData]);

  /**
   * Create invitation and add variables.
   */
  const createInvitationWithVariables = useCallback(async () => {
    if (!templateIdentifier || !actionIdentifier || !roleIdentifier || !template) return;

    setIsProcessing(true);
    setStatus('Creating invitation...');

    try {
      // Create invitation
      const tracked = await invitationController.createInvitation(
        templateIdentifier,
        actionIdentifier,
      );

      let inv = tracked.invitation;
      const invId = inv.invitationIdentifier;
      setInvitationId(invId);

      // Add variables if any
      if (variables.length > 0) {
        const variableData = variables.map(v => {
          // Determine if this is a numeric type that should be BigInt
          // Template types include: 'integer', 'number', 'satoshis'
          // Hints include: 'satoshis', 'amount'
          const isNumeric = ['integer', 'number', 'satoshis'].includes(v.type) ||
                           (v.hint && ['satoshis', 'amount'].includes(v.hint));
          
          return {
            variableIdentifier: v.id,
            roleIdentifier: roleIdentifier,
            value: isNumeric ? BigInt(v.value || '0') : v.value,
          };
        });
        const updated = await invitationController.addVariables(invId, variableData);
        inv = updated.invitation;
      }

      // Add template-required outputs for the current role
      // This is critical - the template defines which outputs the initiator must create
      const action = template.actions?.[actionIdentifier];
      const transaction = action?.transaction ? template.transactions?.[action.transaction] : null;
      
      if (transaction?.outputs && transaction.outputs.length > 0) {
        setStatus('Adding required outputs...');
        
        // Add each required output with just its identifier
        // IMPORTANT: Do NOT pass roleIdentifier here - if roleIdentifier is set,
        // the engine skips generating the lockingBytecode (see engine.ts appendInvitation)
        // The engine will automatically generate the locking bytecode based on the template
        const outputsToAdd = transaction.outputs.map((outputId: string) => ({
          outputIdentifier: outputId,
          // Note: roleIdentifier intentionally omitted to trigger lockingBytecode generation
        }));
        
        const updated = await invitationController.addOutputs(invId, outputsToAdd);
        inv = updated.invitation;
      }

      setInvitation(inv);

      // Check if next step is inputs
      const nextStepType = steps[currentStep + 1]?.type;
      if (nextStepType === 'inputs') {
        setCurrentStep(prev => prev + 1);
        // Load UTXOs after step change
        setTimeout(() => loadAvailableUtxos(), 100);
      } else {
        setCurrentStep(prev => prev + 1);
      }

      setStatus('Invitation created');
    } catch (error) {
      showError(`Failed to create invitation: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setIsProcessing(false);
    }
  }, [templateIdentifier, actionIdentifier, roleIdentifier, template, variables, invitationController, steps, currentStep, showError, setStatus, loadAvailableUtxos]);

  /**
   * Add selected inputs and change output to invitation.
   */
  const addInputsAndOutputs = useCallback(async () => {
    if (!invitationId || !invitation) return;

    const selectedUtxos = availableUtxos.filter(u => u.selected);
    
    if (selectedUtxos.length === 0) {
      showError('Please select at least one UTXO');
      return;
    }

    if (selectedAmount < requiredAmount + fee) {
      showError(`Insufficient funds. Need ${formatSatoshis(requiredAmount + fee)}, selected ${formatSatoshis(selectedAmount)}`);
      return;
    }

    if (changeAmount < 546n) { // Dust threshold
      showError(`Change amount (${changeAmount}) is below dust threshold (546 sats)`);
      return;
    }

    setIsProcessing(true);
    setStatus('Adding inputs and outputs...');

    try {
      // Add inputs
      const inputs = selectedUtxos.map(utxo => ({
        outpointTransactionHash: utxo.outpointTransactionHash,
        outpointIndex: utxo.outpointIndex,
      }));
      
      await invitationController.addInputs(invitationId, inputs);

      // Add change output
      const outputs = [{
        valueSatoshis: changeAmount,
        // The engine will automatically generate the locking bytecode for change
      }];
      
      await invitationController.addOutputs(invitationId, outputs);

      // Add transaction metadata
      // Note: This would be done via appendInvitation but we don't have direct access here
      // The engine should handle defaults

      setCurrentStep(prev => prev + 1);
      setStatus('Inputs and outputs added');
    } catch (error) {
      showError(`Failed to add inputs/outputs: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setIsProcessing(false);
    }
  }, [invitationId, invitation, availableUtxos, selectedAmount, requiredAmount, fee, changeAmount, invitationController, showError, setStatus]);

  /**
   * Publish invitation.
   */
  const publishInvitation = useCallback(async () => {
    if (!invitationId) return;

    setIsProcessing(true);
    setStatus('Publishing invitation...');

    try {
      await invitationController.publishAndSubscribe(invitationId);
      setCurrentStep(prev => prev + 1);
      setStatus('Invitation published');
    } catch (error) {
      showError(`Failed to publish: ${error instanceof Error ? error.message : String(error)}`);
    } finally {
      setIsProcessing(false);
    }
  }, [invitationId, invitationController, showError, setStatus]);

  /**
   * Navigate to previous step.
   */
  const previousStep = useCallback(() => {
    if (currentStep <= 0) {
      goBack();
      return;
    }
    setCurrentStep(prev => prev - 1);
    setFocusArea('content');
    setFocusedInput(0);
  }, [currentStep, goBack]);

  /**
   * Cancel wizard.
   */
  const cancel = useCallback(() => {
    goBack();
  }, [goBack]);

  /**
   * Copy invitation ID to clipboard.
   */
  const copyId = useCallback(async () => {
    if (!invitationId) return;

    try {
      await copyToClipboard(invitationId);
      showInfo(`Copied to clipboard!\n\n${invitationId}`);
    } catch (error) {
      showError(`Failed to copy: ${error instanceof Error ? error.message : String(error)}`);
    }
  }, [invitationId, showInfo, showError]);

  /**
   * Update variable value.
   */
  const updateVariable = useCallback((index: number, value: string) => {
    setVariables(prev => {
      const updated = [...prev];
      const variable = updated[index];
      if (variable) {
        updated[index] = { ...variable, value };
      }
      return updated;
    });
  }, []);

  // Handle keyboard navigation
  useInput((input, key) => {
    // Tab to switch between content and buttons
    if (key.tab) {
      if (focusArea === 'content') {
        // Handle tab based on current step type
        if (currentStepData?.type === 'variables' && variables.length > 0) {
          if (focusedInput < variables.length - 1) {
            setFocusedInput(prev => prev + 1);
            return;
          }
        }
        if (currentStepData?.type === 'inputs' && availableUtxos.length > 0) {
          if (selectedUtxoIndex < availableUtxos.length - 1) {
            setSelectedUtxoIndex(prev => prev + 1);
            return;
          }
        }
        setFocusArea('buttons');
        setFocusedButton('next');
      } else {
        if (focusedButton === 'back') {
          setFocusedButton('cancel');
        } else if (focusedButton === 'cancel') {
          setFocusedButton('next');
        } else {
          setFocusArea('content');
          setFocusedInput(0);
          setSelectedUtxoIndex(0);
        }
      }
      return;
    }

    // Arrow keys for UTXO selection
    if (focusArea === 'content' && currentStepData?.type === 'inputs') {
      if (key.upArrow) {
        setSelectedUtxoIndex(prev => Math.max(0, prev - 1));
      } else if (key.downArrow) {
        setSelectedUtxoIndex(prev => Math.min(availableUtxos.length - 1, prev + 1));
      } else if (key.return || input === ' ') {
        toggleUtxoSelection(selectedUtxoIndex);
      }
      return;
    }

    // Arrow keys in buttons area
    if (focusArea === 'buttons') {
      if (key.leftArrow) {
        setFocusedButton(prev => 
          prev === 'next' ? 'cancel' : prev === 'cancel' ? 'back' : 'back'
        );
      } else if (key.rightArrow) {
        setFocusedButton(prev => 
          prev === 'back' ? 'cancel' : prev === 'cancel' ? 'next' : 'next'
        );
      }
    }

    // Enter on buttons
    if (key.return && focusArea === 'buttons') {
      if (focusedButton === 'back') previousStep();
      else if (focusedButton === 'cancel') cancel();
      else if (focusedButton === 'next') nextStep();
    }

    // 'c' to copy on publish step
    if (input === 'c' && currentStepData?.type === 'publish' && invitationId) {
      copyId();
    }

    // 'a' to select all UTXOs
    if (input === 'a' && currentStepData?.type === 'inputs') {
      setAvailableUtxos(prev => prev.map(u => ({ ...u, selected: true })));
    }

    // 'n' to deselect all UTXOs
    if (input === 'n' && currentStepData?.type === 'inputs') {
      setAvailableUtxos(prev => prev.map(u => ({ ...u, selected: false })));
    }
  });

  // Get action details
  const action = template?.actions?.[actionIdentifier ?? ''];
  const actionName = action?.name || actionIdentifier || 'Unknown';

  // Render step content
  const renderStepContent = () => {
    if (!currentStepData) return null;

    switch (currentStepData.type) {
      case 'info':
        return (
          <Box flexDirection="column">
            <Text color={colors.primary} bold>Action: {actionName}</Text>
            <Text color={colors.textMuted}>{action?.description || 'No description'}</Text>
            <Box marginTop={1}>
              <Text color={colors.text}>Your Role: </Text>
              <Text color={colors.accent}>{roleIdentifier}</Text>
            </Box>
            
            {action?.roles?.[roleIdentifier ?? '']?.requirements && (
              <Box marginTop={1} flexDirection="column">
                <Text color={colors.text}>Requirements:</Text>
                {action.roles[roleIdentifier ?? '']?.requirements?.variables?.map(v => (
                  <Text key={v} color={colors.textMuted}>  • Variable: {v}</Text>
                ))}
                {action.roles[roleIdentifier ?? '']?.requirements?.slots && (
                  <Text color={colors.textMuted}>  • Slots: {action.roles[roleIdentifier ?? '']?.requirements?.slots?.min} min (UTXO selection required)</Text>
                )}
              </Box>
            )}
          </Box>
        );

      case 'variables':
        return (
          <Box flexDirection="column">
            <Text color={colors.text} bold>Enter required values:</Text>
            <Box marginTop={1} flexDirection="column">
              {variables.map((variable, index) => (
                <Box key={variable.id} flexDirection="column" marginBottom={1}>
                  <Text color={colors.primary}>{variable.name}</Text>
                  {variable.hint && (
                    <Text color={colors.textMuted} dimColor>({variable.hint})</Text>
                  )}
                  <Box
                    borderStyle="single"
                    borderColor={focusArea === 'content' && focusedInput === index ? colors.focus : colors.border}
                    paddingX={1}
                    marginTop={1}
                  >
                    <TextInput
                      value={variable.value}
                      onChange={value => updateVariable(index, value)}
                      focus={focusArea === 'content' && focusedInput === index}
                      placeholder={`Enter ${variable.name}...`}
                    />
                  </Box>
                </Box>
              ))}
            </Box>
          </Box>
        );

      case 'inputs':
        return (
          <Box flexDirection="column">
            <Text color={colors.text} bold>Select UTXOs to fund the transaction:</Text>
            
            <Box marginTop={1} flexDirection="column">
              <Text color={colors.textMuted}>
                Required: {formatSatoshis(requiredAmount)} + {formatSatoshis(fee)} fee
              </Text>
              <Text color={selectedAmount >= requiredAmount + fee ? colors.success : colors.warning}>
                Selected: {formatSatoshis(selectedAmount)}
              </Text>
              {selectedAmount > requiredAmount + fee && (
                <Text color={colors.info}>
                  Change: {formatSatoshis(changeAmount)}
                </Text>
              )}
            </Box>

            <Box marginTop={1} flexDirection="column" borderStyle="single" borderColor={colors.border} paddingX={1}>
              {availableUtxos.length === 0 ? (
                <Text color={colors.textMuted}>No UTXOs available</Text>
              ) : (
                availableUtxos.map((utxo, index) => (
                  <Box key={`${utxo.outpointTransactionHash}:${utxo.outpointIndex}`}>
                    <Text
                      color={selectedUtxoIndex === index && focusArea === 'content' ? colors.focus : colors.text}
                      bold={selectedUtxoIndex === index && focusArea === 'content'}
                    >
                      {selectedUtxoIndex === index && focusArea === 'content' ? '▸ ' : '  '}
                      [{utxo.selected ? 'X' : ' '}] {formatSatoshis(utxo.valueSatoshis)} - {formatHex(utxo.outpointTransactionHash, 12)}:{utxo.outpointIndex}
                    </Text>
                  </Box>
                ))
              )}
            </Box>

            <Box marginTop={1}>
              <Text color={colors.textMuted} dimColor>
                Space/Enter: Toggle • a: Select all • n: Deselect all
              </Text>
            </Box>
          </Box>
        );

      case 'review':
        const selectedUtxos = availableUtxos.filter(u => u.selected);
        return (
          <Box flexDirection="column">
            <Text color={colors.text} bold>Review your invitation:</Text>
            
            <Box marginTop={1} flexDirection="column">
              <Text color={colors.textMuted}>Template: {template?.name}</Text>
              <Text color={colors.textMuted}>Action: {actionName}</Text>
              <Text color={colors.textMuted}>Role: {roleIdentifier}</Text>
            </Box>
            
            {variables.length > 0 && (
              <Box marginTop={1} flexDirection="column">
                <Text color={colors.text}>Variables:</Text>
                {variables.map(v => (
                  <Text key={v.id} color={colors.textMuted}>
                    {'  '}{v.name}: {v.value || '(empty)'}
                  </Text>
                ))}
              </Box>
            )}

            {selectedUtxos.length > 0 && (
              <Box marginTop={1} flexDirection="column">
                <Text color={colors.text}>Inputs ({selectedUtxos.length}):</Text>
                {selectedUtxos.slice(0, 3).map(u => (
                  <Text key={`${u.outpointTransactionHash}:${u.outpointIndex}`} color={colors.textMuted}>
                    {'  '}{formatSatoshis(u.valueSatoshis)}
                  </Text>
                ))}
                {selectedUtxos.length > 3 && (
                  <Text color={colors.textMuted}>  ...and {selectedUtxos.length - 3} more</Text>
                )}
              </Box>
            )}

            {changeAmount > 0 && (
              <Box marginTop={1} flexDirection="column">
                <Text color={colors.text}>Outputs:</Text>
                <Text color={colors.textMuted}>  Change: {formatSatoshis(changeAmount)}</Text>
              </Box>
            )}
            
            <Box marginTop={1}>
              <Text color={colors.warning}>
                Press Next to create and publish the invitation.
              </Text>
            </Box>
          </Box>
        );

      case 'publish':
        return (
          <Box flexDirection="column">
            <Text color={colors.success} bold>✓ Invitation Created & Published!</Text>
            <Box marginTop={1} flexDirection="column">
              <Text color={colors.text}>Invitation ID:</Text>
              <Box 
                borderStyle="single" 
                borderColor={colors.primary}
                paddingX={1}
                marginTop={1}
              >
                <Text color={colors.accent}>{invitationId}</Text>
              </Box>
            </Box>
            
            <Box marginTop={1}>
              <Text color={colors.textMuted}>
                Share this ID with the other party to complete the transaction.
              </Text>
            </Box>
            
            <Box marginTop={1}>
              <Text color={colors.warning}>Press 'c' to copy ID to clipboard</Text>
            </Box>
          </Box>
        );

      default:
        return null;
    }
  };

  // Convert steps to StepIndicator format
  const stepIndicatorSteps: Step[] = steps.map(s => ({ label: s.name }));

  return (
    <Box flexDirection="column" flexGrow={1}>
      {/* Header */}
      <Box borderStyle="single" borderColor={colors.secondary} paddingX={1} flexDirection="column">
        <Text color={colors.primary} bold>{logoSmall} - Action Wizard</Text>
        <Text color={colors.textMuted}>
          {template?.name} {'>'} {actionName} (as {roleIdentifier})
        </Text>
      </Box>

      {/* Progress indicator */}
      <Box marginTop={1} paddingX={1}>
        <StepIndicator steps={stepIndicatorSteps} currentStep={currentStep} />
      </Box>

      {/* Content area */}
      <Box
        borderStyle="single"
        borderColor={focusArea === 'content' ? colors.focus : colors.primary}
        flexDirection="column"
        paddingX={1}
        paddingY={1}
        marginTop={1}
        marginX={1}
        flexGrow={1}
      >
        <Text color={colors.primary} bold>
          {' '}{currentStepData?.name} ({currentStep + 1}/{steps.length}){' '}
        </Text>
        <Box marginTop={1}>
          {isProcessing ? (
            <Text color={colors.info}>Processing...</Text>
          ) : (
            renderStepContent()
          )}
        </Box>
      </Box>

      {/* Buttons */}
      <Box marginTop={1} marginX={1} justifyContent="space-between">
        <Box gap={1}>
          <Button 
            label="Back" 
            focused={focusArea === 'buttons' && focusedButton === 'back'}
            disabled={currentStepData?.type === 'publish'}
          />
          <Button 
            label="Cancel" 
            focused={focusArea === 'buttons' && focusedButton === 'cancel'}
          />
        </Box>
        <Button 
          label={currentStepData?.type === 'publish' ? 'Done' : 'Next'}
          focused={focusArea === 'buttons' && focusedButton === 'next'}
          disabled={isProcessing}
        />
      </Box>

      {/* Help text */}
      <Box marginTop={1} marginX={1}>
        <Text color={colors.textMuted} dimColor>
          Tab: Navigate • Enter: Select • Esc: Back
          {currentStepData?.type === 'publish' ? ' • c: Copy ID' : ''}
        </Text>
      </Box>
    </Box>
  );
}
