import React, { useState, useEffect, useMemo } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Combobox } from '@/components/Combobox';
import { Loader2, Plus, X } from 'lucide-react';
import { format } from 'date-fns';

export default function ExpenseBundleSelector({ associationId, selectedIds, onSelectionChange }) {
  const [expenses, setExpenses] = useState([]);
  const [feeSchedules, setFeeSchedules] = useState([]);
  const [loading, setLoading] = useState(false);
  const [rows, setRows] = useState(['']);

  useEffect(() => {
    if (associationId) {
      fetchExpenses();
    } else {
      setExpenses([]);
      setFeeSchedules([]);
      setRows(['']);
    }
  }, [associationId]);

  useEffect(() => {
    const ids = Array.from(selectedIds);
    setRows((currentRows) => {
      const filledRows = currentRows.filter(Boolean);
      const hasSameSelection =
        filledRows.length === ids.length &&
        filledRows.every((id) => ids.includes(id));

      if (hasSameSelection) {
        return currentRows.length ? currentRows : [''];
      }

      return ids.length ? ids : [''];
    });
  }, [selectedIds, associationId]);

  const fetchExpenses = async () => {
    setLoading(true);
    const [expensesRes, feeRes] = await Promise.all([
      supabase
        .from('billable_expenses')
        .select('*')
        .eq('association_id', associationId)
        .order('date', { ascending: false }),
      supabase
        .from('fee_schedules')
        .select('*')
        .order('description')
    ]);

    if (!expensesRes.error) setExpenses(expensesRes.data || []);
    if (!feeRes.error) setFeeSchedules(feeRes.data || []);
    setLoading(false);
  };

  const allRows = useMemo(() => {
    const existingKeys = new Set(
      expenses.map((expense) => `${expense.description || ''}::${expense.category || ''}::${expense.billable_type || ''}`)
    );

    const universalFees = feeSchedules
      .filter((fee) => !existingKeys.has(`${fee.description || ''}::${fee.category || ''}::${fee.account || ''}`))
      .map((fee) => ({
        id: `fee:${fee.id}`,
        date: null,
        description: fee.description,
        category: fee.category,
        vendor_name: null,
        amount: Number(fee.fee || 0),
        is_credit: false,
        billable_type: fee.account || fee.subcategory || null,
        source: 'fee_schedule',
      }));

    return [
      ...expenses.map((expense) => ({ ...expense, source: 'billable_expense' })),
      ...universalFees,
    ];

  }, [expenses, feeSchedules]);

  const optionMap = useMemo(
    () => new Map(allRows.map((row) => [row.id, row])),
    [allRows]
  );

  const options = useMemo(
    () =>
      allRows.map((row) => ({
        value: row.id,
        label: [
          row.description || 'Untitled fee',
          row.category,
          `$${Math.abs(Number(row.amount || 0)).toFixed(2)}`,
          row.source === 'fee_schedule' ? 'Universal Fee' : 'Existing Fee',
        ]
          .filter(Boolean)
          .join(' • '),
      })),
    [allRows]
  );

  const syncSelection = (nextRows) => {
    onSelectionChange(new Set(nextRows.filter(Boolean)));
  };

  const handleAddRow = () => {
    if (rows.length >= allRows.length) return;
    setRows([...rows, '']);
  };

  const handleRemoveRow = (rowIndex) => {
    const nextRows = rows.filter((_, index) => index !== rowIndex);
    const normalizedRows = nextRows.length ? nextRows : [''];
    setRows(normalizedRows);
    syncSelection(normalizedRows);
  };

  const handleRowChange = (rowIndex, nextValue) => {
    const nextRows = [...rows];
    nextRows[rowIndex] = nextValue;
    setRows(nextRows);
    syncSelection(nextRows);
  };

  const selectedTotal = allRows
    .filter(e => selectedIds.has(e.id))
    .reduce((s, e) => s + (e.is_credit ? -e.amount : e.amount), 0);

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12 text-muted-foreground gap-2">
        <Loader2 className="h-4 w-4 animate-spin" /> Loading expenses...
      </div>
    );
  }

  if (!allRows.length) {
    return (
      <div className="text-center py-12 text-muted-foreground border-2 border-dashed rounded-lg bg-muted/30">
        No billable expenses or fee templates found for this association.
      </div>
    );
  }

  return (
    <div className="space-y-4 rounded-lg border bg-muted/20 p-4">
      <div className="flex items-center justify-between gap-4">
        <div>
          <p className="text-sm font-medium">Bundle fees</p>
          <p className="text-xs text-muted-foreground">Add rows and choose any existing or universal fee.</p>
        </div>
        <div className="flex items-center gap-3 text-sm">
          <span className="text-muted-foreground">
            {selectedIds.size} selected
          </span>
          <Badge variant={selectedTotal >= 0 ? "default" : "secondary"}>
            Total: ${Math.abs(selectedTotal).toFixed(2)}{selectedTotal < 0 ? ' CR' : ''}
          </Badge>
        </div>
      </div>

      <div className="space-y-3">
        {rows.map((rowId, index) => {
          const unavailableIds = new Set(rows.filter((value, valueIndex) => value && valueIndex !== index));
          const rowOptions = options.filter((option) => !unavailableIds.has(option.value));
          const selectedItem = rowId ? optionMap.get(rowId) : null;

          return (
            <div key={`${rowId || 'empty'}-${index}`} className="rounded-md border bg-background p-3">
              <div className="flex items-start gap-2">
                <Combobox
                  options={rowOptions}
                  value={rowId}
                  onChange={(value) => handleRowChange(index, value)}
                  placeholder="Select a fee"
                  emptyText="No fees available"
                  className="h-10 flex-1"
                />
                <Button
                  type="button"
                  variant="outline"
                  size="icon"
                  onClick={() => handleRemoveRow(index)}
                  disabled={!rowId && rows.length === 1}
                  aria-label="Remove fee row"
                >
                  <X className="h-4 w-4" />
                </Button>
              </div>

              {selectedItem && (
                <div className="mt-2 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
                  <Badge variant="outline">{selectedItem.source === 'fee_schedule' ? 'Universal Fee' : 'Existing Fee'}</Badge>
                  <span>{selectedItem.category || 'Uncategorized'}</span>
                  {selectedItem.vendor_name && <span>{selectedItem.vendor_name}</span>}
                  {selectedItem.date && <span>{format(new Date(`${selectedItem.date}T12:00:00`), 'MM/dd/yy')}</span>}
                  <span>
                    {selectedItem.is_credit ? '-' : ''}${Math.abs(Number(selectedItem.amount || 0)).toFixed(2)}
                  </span>
                </div>
              )}
            </div>
          );
        })}
      </div>

      <Button
        type="button"
        variant="outline"
        onClick={handleAddRow}
        disabled={rows.filter(Boolean).length >= allRows.length}
        className="w-full"
      >
        <Plus className="mr-2 h-4 w-4" />
        Add row
      </Button>
    </div>
  );
}
