
import React, { useEffect, useState, useMemo } from 'react';
import { useForm } from 'react-hook-form';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Loader2, DollarSign, AlertCircle, Plus, Trash2 } from 'lucide-react';
import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';

export default function PaymentFormDialog({ open, onOpenChange, vendorId, clientId, onSuccess }) {
  const { register, handleSubmit, reset, watch, formState: { errors, isSubmitting } } = useForm({
    defaultValues: { amount: '', payment_date: new Date().toISOString().split('T')[0], reference: '', notes: '' }
  });
  const paymentAmount = watch('amount');
  const { toast } = useToast();

  const [vendors, setVendors] = useState([]);
  const [clients, setClients] = useState([]);
  const [selectedVendorId, setSelectedVendorId] = useState(vendorId || '');
  const [selectedClientId, setSelectedClientId] = useState(clientId || '');
  const [allocations, setAllocations] = useState([]);
  const [accounts, setAccounts] = useState([]);
  const [accountsLoading, setAccountsLoading] = useState(false);

  useEffect(() => {
    if (open) {
      reset({ amount: '', payment_date: new Date().toISOString().split('T')[0], reference: '', notes: '' });
      setSelectedVendorId(vendorId || '');
      setSelectedClientId(clientId || '');
      setAllocations([]);
      fetchInitialData();
    }
  }, [open, vendorId, clientId, reset]);

  const fetchInitialData = async () => {
    const [{ data: vData }, { data: cData }] = await Promise.all([
      supabase.from('vendors').select('id, vendor_name').order('vendor_name'),
      supabase.from('associations').select('id, name').eq('status', 'active').order('name')
    ]);
    setVendors(vData || []);
    setClients(cData || []);
  };

  useEffect(() => {
    if (selectedClientId) {
      setAccountsLoading(true);
      supabase.from('chart_of_accounts').select('*, association_ids').eq('is_active', true).order('account_number')
        .then(({ data }) => {
          const filtered = (data || []).filter(a => {
            const ids = a.association_ids || [];
            return ids.includes(selectedClientId) || a.association_id === selectedClientId;
          });
          setAccounts(filtered);
          setAccountsLoading(false);
        });
    }
  }, [selectedClientId]);

  const handleAddRow = () => {
    setAllocations([...allocations, { id: crypto.randomUUID(), accountId: '', balance: 0, amount: '' }]);
  };

  const handleRemoveRow = (id) => {
    setAllocations(allocations.filter(a => a.id !== id));
  };

  const handleAllocationChange = (id, field, value) => {
    setAllocations(allocations.map(a => {
      if (a.id === id) {
        const updated = { ...a, [field]: value };
        if (field === 'accountId') {
          const acc = accounts.find(ac => ac.id === value);
          updated.balance = acc ? parseFloat(acc.current_balance || 0) : 0;
        }
        return updated;
      }
      return a;
    }));
  };

  const totalAllocated = useMemo(() => allocations.reduce((sum, a) => sum + (parseFloat(a.amount) || 0), 0), [allocations]);
  const paymentTotal = parseFloat(paymentAmount) || 0;
  const allocationDifference = paymentTotal - totalAllocated;
  const isAllocationValid = Math.abs(allocationDifference) < 0.01 &&
    allocations.every(a => a.accountId && parseFloat(a.amount) > 0 && parseFloat(a.amount) <= a.balance) &&
    allocations.length > 0;

  const onSubmit = async (data) => {
    if (!selectedVendorId) { toast({ variant: 'destructive', title: 'Error', description: 'Vendor is required.' }); return; }
    if (!selectedClientId) { toast({ variant: 'destructive', title: 'Error', description: 'Association is required.' }); return; }
    if (allocations.length > 0 && !isAllocationValid) {
      toast({ variant: 'destructive', title: 'Error', description: 'Allocations must match total and not exceed balances.' }); return;
    }

    try {
      const payload = {
        vendor_id: selectedVendorId, association_id: selectedClientId,
        amount: parseFloat(data.amount), payment_date: data.payment_date,
        reference: data.reference, notes: data.notes
      };

      const { data: insertedPayment, error: paymentError } = await supabase.from('admin_payments').insert([{
        association_id: selectedClientId, amount: parseFloat(data.amount),
        payment_date: data.payment_date, reference_number: data.reference,
        description: data.notes, status: 'completed'
      }]).select('id').single();
      if (paymentError) throw paymentError;

      if (allocations.length > 0) {
        const { data: userData } = await supabase.auth.getUser();
        const userId = userData?.user?.id;

        const journalEntries = allocations.map(alloc => ({
          association_id: selectedClientId, date: data.payment_date,
          description: `Payment Allocation: ${data.reference || 'Vendor Payment'}`,
          amount: parseFloat(alloc.amount), type: 'debit',
          chart_of_account_id: alloc.accountId, created_by: userId
        }));

        const { error: jeError } = await supabase.from('journal_entries').insert(journalEntries);
        if (jeError) {
          console.error("Journal Entry Error:", jeError);
          toast({ variant: 'destructive', title: 'Warning', description: 'Payment saved, but allocations failed to post.' });
        }
      }

      toast({ title: 'Success', description: 'Payment recorded successfully.' });
      onSuccess?.();
      onOpenChange(false);
    } catch (err) {
      console.error(err);
      toast({ variant: 'destructive', title: 'Error', description: 'Failed to record payment.' });
    }
  };

  const formatCurrency = (val) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(val || 0);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[700px] max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle className="text-xl">Record Payment</DialogTitle>
          <DialogDescription>Record an outgoing payment and apply it to outstanding balances.</DialogDescription>
        </DialogHeader>
        <form onSubmit={handleSubmit(onSubmit)} className="space-y-6 py-4">
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Association <span className="text-destructive">*</span></Label>
              <Select value={selectedClientId} onValueChange={setSelectedClientId} disabled={!!clientId}>
                <SelectTrigger><SelectValue placeholder="Select association" /></SelectTrigger>
                <SelectContent>{clients.map(c => <SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>)}</SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>Vendor <span className="text-destructive">*</span></Label>
              <Select value={selectedVendorId} onValueChange={setSelectedVendorId} disabled={!!vendorId}>
                <SelectTrigger><SelectValue placeholder="Select vendor" /></SelectTrigger>
                <SelectContent>{vendors.map(v => <SelectItem key={v.id} value={v.id}>{v.vendor_name}</SelectItem>)}</SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4 bg-muted/50 p-4 rounded-lg border">
            <div className="space-y-2">
              <Label className="font-semibold">Total Amount <span className="text-destructive">*</span></Label>
              <div className="relative">
                <DollarSign className="absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
                <Input type="number" step="0.01" className="pl-9 text-lg font-medium" {...register('amount', { required: true, min: 0.01 })} placeholder="0.00" />
              </div>
              {errors.amount && <span className="text-xs text-destructive font-medium">Required</span>}
            </div>
            <div className="space-y-2">
              <Label className="font-semibold">Payment Date <span className="text-destructive">*</span></Label>
              <Input type="date" className="text-base" {...register('payment_date', { required: true })} />
              {errors.payment_date && <span className="text-xs text-destructive font-medium">Required</span>}
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2"><Label>Reference / Check #</Label><Input {...register('reference')} placeholder="e.g. CHK-12345" /></div>
            <div className="space-y-2"><Label>Notes</Label><Input {...register('notes')} placeholder="Optional details..." /></div>
          </div>

          <div className="pt-4 border-t">
            <div className="flex items-center justify-between mb-4">
              <div>
                <h4 className="font-semibold">Apply payment to balances</h4>
                <p className="text-sm text-muted-foreground">Allocate the payment amount across outstanding accounts.</p>
              </div>
              <Button type="button" variant="outline" size="sm" onClick={handleAddRow} disabled={!selectedClientId}>
                <Plus className="w-4 h-4 mr-2" /> Add row
              </Button>
            </div>

            {!selectedClientId ? (
              <Alert className="bg-amber-50 border-amber-200 text-amber-800">
                <AlertCircle className="h-4 w-4" />
                <AlertDescription>Please select an Association to view and apply to balances.</AlertDescription>
              </Alert>
            ) : (
              <div className="border rounded-lg overflow-hidden bg-background shadow-sm">
                <Table>
                  <TableHeader className="bg-muted">
                    <TableRow>
                      <TableHead className="w-[50%]">Account</TableHead>
                      <TableHead className="text-right">Balance</TableHead>
                      <TableHead className="text-right w-[150px]">Amount</TableHead>
                      <TableHead className="w-[50px]"></TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {allocations.length === 0 ? (
                      <TableRow><TableCell colSpan={4} className="text-center text-muted-foreground py-6 italic">No accounts allocated. Click "Add row" to distribute funds.</TableCell></TableRow>
                    ) : allocations.map((alloc) => (
                      <TableRow key={alloc.id}>
                        <TableCell>
                          <Select value={alloc.accountId} onValueChange={(val) => handleAllocationChange(alloc.id, 'accountId', val)} disabled={accountsLoading}>
                            <SelectTrigger><SelectValue placeholder="Select account..." /></SelectTrigger>
                            <SelectContent>{accounts.map(ac => <SelectItem key={ac.id} value={ac.id}>{ac.account_number} - {ac.account_name}</SelectItem>)}</SelectContent>
                          </Select>
                        </TableCell>
                        <TableCell className="text-right font-medium">{formatCurrency(alloc.balance)}</TableCell>
                        <TableCell>
                          <div className="relative">
                            <span className="absolute left-2 top-2 text-muted-foreground text-sm">$</span>
                            <Input type="number" step="0.01" min="0.01" value={alloc.amount}
                              onChange={(e) => handleAllocationChange(alloc.id, 'amount', e.target.value)}
                              className={`pl-6 h-9 text-right ${parseFloat(alloc.amount) > alloc.balance ? 'border-destructive text-destructive focus-visible:ring-destructive' : ''}`}
                              placeholder="0.00" />
                          </div>
                          {parseFloat(alloc.amount) > alloc.balance && <div className="text-[10px] text-destructive mt-1 absolute leading-tight">Exceeds balance</div>}
                        </TableCell>
                        <TableCell>
                          <Button type="button" variant="ghost" size="icon" onClick={() => handleRemoveRow(alloc.id)} className="text-muted-foreground hover:text-destructive hover:bg-destructive/10 h-8 w-8">
                            <Trash2 className="w-4 h-4" />
                          </Button>
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>

                {allocations.length > 0 && (
                  <div className="bg-muted/50 p-4 border-t">
                    <div className="flex justify-end gap-8 text-sm">
                      <div className="text-right space-y-2">
                        <div className="text-muted-foreground">Payment total:</div>
                        <div className="text-muted-foreground">Total allocated:</div>
                        <div className={`font-semibold ${Math.abs(allocationDifference) > 0.01 ? 'text-destructive' : 'text-emerald-600'}`}>Difference:</div>
                      </div>
                      <div className="text-right space-y-2 font-medium">
                        <div>{formatCurrency(paymentTotal)}</div>
                        <div>{formatCurrency(totalAllocated)}</div>
                        <div className={Math.abs(allocationDifference) > 0.01 ? 'text-destructive' : 'text-emerald-600'}>{formatCurrency(allocationDifference)}</div>
                      </div>
                    </div>
                    {Math.abs(allocationDifference) > 0.01 && (
                      <p className="text-xs text-destructive text-right mt-3 flex items-center justify-end gap-1">
                        <AlertCircle className="w-3 h-3" /> The allocated amount must equal the payment total.
                      </p>
                    )}
                  </div>
                )}
              </div>
            )}
          </div>

          <DialogFooter className="pt-4 border-t">
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>Cancel</Button>
            <Button type="submit" disabled={isSubmitting || (allocations.length > 0 && !isAllocationValid)}>
              {isSubmitting && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
              Save Payment
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
