import { useMemo, useState } from "react";
import { Pressable, StyleSheet, Text, View } from "react-native";
import { Ionicons } from "@expo/vector-icons";

import { Button } from "@/components/ui/Button";
import { fonts, spacing } from "@/constants/theme";
import { useAppTheme } from "@/contexts/ThemeContext";
import { formatCurrency } from "@/lib/format";
import type { ReceiptLineItem } from "@/lib/receipt-parse";

export type ReceiptSplitSelection = {
  selectedItemIds: string[];
  selectedSubtotal: number;
  allocatedTax: number;
  owedTotal: number;
  notes: string;
};

type ReceiptItemSelectorProps = {
  items: ReceiptLineItem[];
  subtotal: number | null;
  tax: number | null;
  total: number | null;
  onApply: (selection: ReceiptSplitSelection) => void;
};

export function ReceiptItemSelector({
  items,
  subtotal,
  tax,
  total,
  onApply,
}: ReceiptItemSelectorProps) {
  const { colors } = useAppTheme();
  const [selectedIds, setSelectedIds] = useState<Set<string>>(
    () => new Set(items.length === 1 ? [items[0]!.id] : []),
  );

  const calculation = useMemo(() => {
    const selected = items.filter((item) => selectedIds.has(item.id));
    const selectedSubtotal = roundMoney(
      selected.reduce((sum, item) => sum + item.amount, 0),
    );
    const receiptSubtotal =
      subtotal && subtotal > 0
        ? subtotal
        : roundMoney(items.reduce((sum, item) => sum + item.amount, 0));
    const knownTax =
      tax ??
      (total && receiptSubtotal > 0
        ? Math.max(0, roundMoney(total - receiptSubtotal))
        : 0);
    const allocatedTax =
      receiptSubtotal > 0
        ? roundMoney(knownTax * (selectedSubtotal / receiptSubtotal))
        : 0;
    const owedTotal = roundMoney(selectedSubtotal + allocatedTax);
    const notes = [
      "Receipt split",
      ...selected.map(
        (item) => `- ${item.name}: ${formatCurrency(item.amount)}`,
      ),
      `Selected subtotal: ${formatCurrency(selectedSubtotal)}`,
      `Allocated tax: ${formatCurrency(allocatedTax)}`,
      `Owed total: ${formatCurrency(owedTotal)}`,
    ].join("\n");

    return { selected, selectedSubtotal, allocatedTax, owedTotal, notes };
  }, [items, selectedIds, subtotal, tax, total]);

  if (items.length === 0) return null;

  const toggle = (id: string) => {
    setSelectedIds((current) => {
      const next = new Set(current);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  return (
    <View style={[styles.wrap, { borderColor: colors.border }]}>
      <View style={styles.header}>
        <View style={styles.headerCopy}>
          <Text style={[styles.title, { color: colors.foreground }]}>
            Select expense items
          </Text>
          <Text style={[styles.subtitle, { color: colors.mutedForeground }]}>
            Pick only the receipt lines that should become this expense. Tax is
            split proportionally.
          </Text>
        </View>
        <Text style={[styles.total, { color: colors.foreground }]}>
          {formatCurrency(calculation.owedTotal)}
        </Text>
      </View>

      {items.length > 1 ? (
        <View style={styles.bulkActions}>
          <Pressable
            accessibilityRole="button"
            onPress={() =>
              setSelectedIds(new Set(items.map((item) => item.id)))
            }
            style={({ pressed }) => [
              styles.bulkAction,
              pressed && styles.pressed,
            ]}
          >
            <Text style={[styles.bulkActionText, { color: colors.primary }]}>
              Select all
            </Text>
          </Pressable>
          <Pressable
            accessibilityRole="button"
            onPress={() => setSelectedIds(new Set())}
            style={({ pressed }) => [
              styles.bulkAction,
              pressed && styles.pressed,
            ]}
          >
            <Text
              style={[styles.bulkActionText, { color: colors.mutedForeground }]}
            >
              Clear
            </Text>
          </Pressable>
        </View>
      ) : null}

      <View style={styles.itemList}>
        {items.map((item) => {
          const selected = selectedIds.has(item.id);
          return (
            <Pressable
              key={item.id}
              accessibilityRole="checkbox"
              accessibilityState={{ checked: selected }}
              onPress={() => toggle(item.id)}
              style={({ pressed }) => [
                styles.item,
                { borderColor: colors.borderGlass },
                selected && { backgroundColor: colors.muted },
                pressed && styles.pressed,
              ]}
            >
              <Ionicons
                name={selected ? "checkmark-circle" : "ellipse-outline"}
                size={21}
                color={selected ? colors.primary : colors.mutedForeground}
              />
              <Text
                style={[styles.itemName, { color: colors.foreground }]}
                numberOfLines={2}
              >
                {item.name}
              </Text>
              <Text style={[styles.itemAmount, { color: colors.foreground }]}>
                {formatCurrency(item.amount)}
              </Text>
            </Pressable>
          );
        })}
      </View>

      <View style={styles.summary}>
        <SummaryRow label="Items" value={calculation.selectedSubtotal} />
        <SummaryRow label="Tax" value={calculation.allocatedTax} />
        <SummaryRow label="Owed" value={calculation.owedTotal} strong />
      </View>

      <Button
        title={
          calculation.selected.length === 0
            ? "Select an item to apply"
            : "Apply selected items"
        }
        disabled={calculation.selected.length === 0}
        onPress={() =>
          onApply({
            selectedItemIds: calculation.selected.map((item) => item.id),
            selectedSubtotal: calculation.selectedSubtotal,
            allocatedTax: calculation.allocatedTax,
            owedTotal: calculation.owedTotal,
            notes: calculation.notes,
          })
        }
      />
    </View>
  );

  function SummaryRow({
    label,
    value,
    strong,
  }: {
    label: string;
    value: number;
    strong?: boolean;
  }) {
    return (
      <View style={styles.summaryRow}>
        <Text style={[styles.summaryLabel, { color: colors.mutedForeground }]}>
          {label}
        </Text>
        <Text
          style={[
            styles.summaryValue,
            { color: colors.foreground },
            strong && styles.summaryValueStrong,
          ]}
        >
          {formatCurrency(value)}
        </Text>
      </View>
    );
  }
}

function roundMoney(value: number) {
  return Math.round((value + Number.EPSILON) * 100) / 100;
}

const styles = StyleSheet.create({
  wrap: {
    gap: spacing.md,
    borderWidth: 1,
    borderRadius: 16,
    padding: spacing.md,
  },
  header: {
    flexDirection: "row",
    alignItems: "flex-start",
    justifyContent: "space-between",
    gap: spacing.md,
  },
  headerCopy: {
    flex: 1,
    gap: 2,
  },
  title: {
    fontFamily: fonts.bodySemiBold,
    fontSize: 16,
  },
  subtitle: {
    fontFamily: fonts.body,
    fontSize: 13,
    lineHeight: 18,
  },
  total: {
    fontFamily: fonts.bodySemiBold,
    fontSize: 18,
    fontVariant: ["tabular-nums"],
  },
  itemList: {
    gap: spacing.sm,
  },
  bulkActions: {
    flexDirection: "row",
    gap: spacing.sm,
  },
  bulkAction: {
    minHeight: 34,
    justifyContent: "center",
  },
  bulkActionText: {
    fontFamily: fonts.bodyMedium,
    fontSize: 13,
  },
  item: {
    minHeight: 48,
    borderWidth: 1,
    borderRadius: 12,
    paddingHorizontal: spacing.sm,
    paddingVertical: spacing.sm,
    flexDirection: "row",
    alignItems: "center",
    gap: spacing.sm,
  },
  pressed: {
    opacity: 0.85,
  },
  itemName: {
    flex: 1,
    fontFamily: fonts.bodyMedium,
    fontSize: 14,
  },
  itemAmount: {
    fontFamily: fonts.bodySemiBold,
    fontSize: 14,
    fontVariant: ["tabular-nums"],
  },
  summary: {
    gap: spacing.xs,
  },
  summaryRow: {
    flexDirection: "row",
    justifyContent: "space-between",
    gap: spacing.md,
  },
  summaryLabel: {
    fontFamily: fonts.body,
    fontSize: 13,
  },
  summaryValue: {
    fontFamily: fonts.bodyMedium,
    fontSize: 13,
    fontVariant: ["tabular-nums"],
  },
  summaryValueStrong: {
    fontFamily: fonts.bodySemiBold,
    fontSize: 15,
  },
});
