import React, { useEffect, useId, useMemo, useState } from "react";
import { Box, Text } from "ink";

import { ScrollableList, type ListItemData } from "./List.js";
import TextInput from "./TextInput.js";
import { DialogWrapper } from "./Dialog.js";
import { useInputLayer, useLayeredInput } from "../hooks/useInputLayer.js";
import { colors } from "../theme.js";

/**
 * Props for the currency selection dialog.
 */
interface CurrencySelectionDialogProps {
  /** Current wallet currency from persisted settings. */
  currentCurrency: string;
  /** Available fiat numerator symbols that can be paired with BCH. */
  currencies: string[];
  /** True while the dialog is loading available pairs. */
  isLoading: boolean;
  /** Optional loading/error message for pair discovery. */
  errorMessage: string | null;
  /** Called when the user chooses a currency and confirms. */
  onSelectCurrency: (currencyCode: string) => void;
  /** Called when the dialog should close without applying changes. */
  onCancel: () => void;
}

/**
 * Currency picker dialog.
 *
 * UX requirements:
 * - Arrow keys move the highlighted item.
 * - Typing immediately filters results.
 * - Enter applies current selection.
 * - Escape closes without saving.
 */
export function CurrencySelectionDialog({
  currentCurrency,
  currencies,
  isLoading,
  errorMessage,
  onSelectCurrency,
  onCancel,
}: CurrencySelectionDialogProps): React.ReactElement {
  const layerId = useId();
  const [filterText, setFilterText] = useState("");
  const [selectedIndex, setSelectedIndex] = useState(0);

  // Mount this as a capturing input layer so background screens stop handling keys.
  useInputLayer(layerId);

  /**
   * Applies the currently selected filtered result.
   */
  const applySelection = (): void => {
    const selectedCurrency = filteredCurrencies[selectedIndex];
    if (!selectedCurrency) {
      return;
    }
    onSelectCurrency(selectedCurrency);
  };

  useLayeredInput(layerId, (_input, key) => {
    if (key.escape) {
      onCancel();
      return;
    }

    if (key.upArrow) {
      setSelectedIndex((prev) =>
        prev <= 0 ? Math.max(filteredCurrencies.length - 1, 0) : prev - 1,
      );
      return;
    }

    if (key.downArrow) {
      setSelectedIndex((prev) =>
        filteredCurrencies.length === 0
          ? 0
          : prev >= filteredCurrencies.length - 1
            ? 0
            : prev + 1,
      );
      return;
    }

  });

  /**
   * Filter currencies as the user types.
   */
  const filteredCurrencies = useMemo(() => {
    const normalizedFilter = filterText.trim().toUpperCase();
    if (!normalizedFilter) {
      return currencies;
    }
    return currencies.filter((currencyCode) =>
      currencyCode.toUpperCase().includes(normalizedFilter),
    );
  }, [currencies, filterText]);

  /**
   * Keep selected index valid whenever filtering shrinks the result set.
   */
  useEffect(() => {
    if (filteredCurrencies.length === 0) {
      setSelectedIndex(0);
      return;
    }

    if (selectedIndex >= filteredCurrencies.length) {
      setSelectedIndex(filteredCurrencies.length - 1);
    }
  }, [filteredCurrencies, selectedIndex]);

  /**
   * When the dialog opens or the list updates, default to current currency.
   */
  useEffect(() => {
    if (filterText.trim().length > 0) {
      return;
    }

    const currentIndex = filteredCurrencies.findIndex(
      (currencyCode) => currencyCode.toUpperCase() === currentCurrency.toUpperCase(),
    );
    if (currentIndex >= 0) {
      setSelectedIndex(currentIndex);
    }
  }, [filteredCurrencies, currentCurrency, filterText]);

  const listItems: ListItemData<string>[] = filteredCurrencies.map(
    (currencyCode) => ({
      key: currencyCode,
      label: currencyCode,
      description:
        currencyCode.toUpperCase() === currentCurrency.toUpperCase()
          ? "(current)"
          : undefined,
      value: currencyCode,
    }),
  );

  return (
    <DialogWrapper title="Select Fiat Currency" borderColor={colors.info} width={64}>
      <Text color={colors.textMuted}>
        Available BCH quote pairs are loaded from the live rates adapter.
      </Text>

      <Box marginTop={1}>
        <Text color={colors.primary}>Filter:</Text>
      </Box>
      <Box borderStyle="single" borderColor={colors.focus} paddingX={1}>
        <TextInput
          value={filterText}
          onChange={setFilterText}
          onSubmit={() => applySelection()}
          placeholder="Type currency code (e.g. USD, AUD)..."
          focus
        />
      </Box>

      <Box marginTop={1} flexDirection="column">
        {isLoading ? (
          <Text color={colors.textMuted}>Loading available pairs...</Text>
        ) : errorMessage ? (
          <Text color={colors.error}>{errorMessage}</Text>
        ) : (
          <ScrollableList
            items={listItems}
            selectedIndex={selectedIndex}
            onSelect={setSelectedIndex}
            onActivate={() => applySelection()}
            focus={false}
            maxVisible={8}
            emptyMessage="No BCH quote pairs match this filter."
          />
        )}
      </Box>

      <Box marginTop={1}>
        <Text color={colors.textMuted}>
          Type to filter • ↑↓ navigate • Enter apply • Esc cancel
        </Text>
      </Box>
    </DialogWrapper>
  );
}
