import { useMemo } from 'react';
import { type Expense, type Person } from '@splint/shared';
import { Item, ItemContent, ItemDescription } from '@/components/ui/item';

interface Props {
  expenses: Expense[];
  people: Person[];
}

/** Category keywords mapped to display names and colors. */
const CATEGORY_RULES: { keywords: string[]; name: string; color: string }[] = [
  { keywords: ['dinner', 'restaurant', 'lunch', 'breakfast', 'food', 'groceries', 'pizza', 'cafe', 'coffee', 'meal', 'snack', 'sushi', 'burrito', 'taco'], name: 'Food & Drink', color: '#c9a227' },
  { keywords: ['uber', 'taxi', 'lyft', 'gas', 'fuel', 'parking', 'toll', 'bus', 'train', 'subway', 'metro', 'transport', 'flight', 'plane', 'airfare'], name: 'Transport', color: '#6a8fbf' },
  { keywords: ['rent', 'utilities', 'electric', 'water', 'internet', 'wifi', 'phone', 'bill'], name: 'Bills & Utilities', color: '#c94a4a' },
  { keywords: ['movie', 'concert', 'theatre', 'theater', 'game', 'netflix', 'spotify', 'ticket', 'show', 'event', 'bar', 'drinks', 'beer', 'club'], name: 'Entertainment', color: '#a06cd5' },
  { keywords: ['hotel', 'airbnb', 'hostel', 'booking', 'flight', 'travel', 'trip', 'vacation'], name: 'Travel', color: '#5a9e6f' },
  { keywords: ['amazon', 'walmart', 'target', 'shopping', 'clothes', 'shirt', 'pants', 'shoes', 'gadget', 'tech', 'computer', 'phone case'], name: 'Shopping', color: '#d4b13a' },
  { keywords: ['doctor', 'pharmacy', 'medicine', 'hospital', 'dentist', 'health', 'gym', 'fitness'], name: 'Health', color: '#e06c75' },
];

function inferCategory(description: string): string {
  const lower = description.toLowerCase();
  for (const rule of CATEGORY_RULES) {
    if (rule.keywords.some((kw) => lower.includes(kw))) return rule.name;
  }
  return 'Other';
}

function getCategoryColor(cat: string): string {
  return CATEGORY_RULES.find((r) => r.name === cat)?.color ?? '#8a8278';
}

/**
 * Category breakdown bar chart derived from expense descriptions.
 * Each expense is assigned a category via keyword matching.
 */
export function CategoryBreakdown({ expenses, people }: Props) {
  const breakdown = useMemo(() => {
    const map = new Map<string, number>(); // category → total cents
    for (const e of expenses) {
      const cat = inferCategory(e.description);
      map.set(cat, (map.get(cat) ?? 0) + e.amount);
    }
    const total = Array.from(map.values()).reduce((a, b) => a + b, 0);
    return { map, total };
  }, [expenses]);

  if (expenses.length === 0) {
    return <p className="text-xs text-muted-foreground">No expenses to categorize yet.</p>;
  }

  const sorted = Array.from(breakdown.map.entries()).sort((a, b) => b[1] - a[1]);

  return (
    <div role="img" aria-label={`Spending breakdown across ${sorted.length} categories`}>
      {sorted.map(([cat, amount]) => {
        const pct = breakdown.total > 0 ? (amount / breakdown.total) * 100 : 0;
        return (
          <Item key={cat} variant="default" size="xs" className="flex-col gap-1">
            <ItemContent>
              <ItemDescription className="flex items-center gap-1.5 w-full justify-between">
                <span className="flex items-center gap-1.5">
                  <span
                    className="inline-block shrink-0 rounded-none"
                    style={{ width: 10, height: 10, background: getCategoryColor(cat) }}
                  />
                  <span>{cat}</span>
                </span>
                <span>${(amount / 100).toFixed(2)} ({pct.toFixed(0)}%)</span>
              </ItemDescription>
            </ItemContent>
            <div className="balance-bar w-full" style={{ height: 6 }}>
              <div
                className="balance-bar-fill credit"
                style={{
                  width: `${Math.max(pct, 2)}%`,
                  background: getCategoryColor(cat),
                }}
              />
            </div>
          </Item>
        );
      })}
    </div>
  );
}
