
import React, { useState, useEffect } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Progress } from '@/components/ui/progress';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { ScrollArea } from '@/components/ui/scroll-area';
import { useToast } from '@/hooks/use-toast';
import { Loader2, AlertCircle, CheckCircle2, PlayCircle, RefreshCw } from 'lucide-react';
import { supabase } from '@/integrations/supabase/client';
import { format, addDays, addWeeks, addMonths, addQuarters, addYears } from 'date-fns';

export default function ProcessRecurringTransactionsDialog({ open, onOpenChange, clientId, onProcessed }) {
  const { toast } = useToast();
  const [loading, setLoading] = useState(false);
  const [dueTransactions, setDueTransactions] = useState([]);
  const [selectedIds, setSelectedIds] = useState(new Set());
  const [processingState, setProcessingState] = useState('idle');
  const [progress, setProgress] = useState(0);
  const [results, setResults] = useState({ success: [], failed: [] });

  useEffect(() => {
    if (open && clientId) {
      fetchDueTransactions();
      setProcessingState('idle'); setProgress(0);
      setResults({ success: [], failed: [] }); setSelectedIds(new Set());
    }
  }, [open, clientId]);

  const fetchDueTransactions = async () => {
    try {
      setLoading(true);
      const today = new Date().toISOString().split('T')[0];
      const { data, error } = await supabase
        .from('recurring_transactions').select('*')
        .eq('association_id', clientId).eq('status', 'active')
        .lte('next_run_date', today).order('next_run_date', { ascending: true });
      if (error) throw error;
      setDueTransactions(data || []);
      if (data) setSelectedIds(new Set(data.map(t => t.id)));
    } catch (error) {
      console.error('Error fetching due transactions:', error);
      toast({ variant: 'destructive', title: 'Error', description: 'Failed to load due recurring transactions.' });
    } finally { setLoading(false); }
  };

  const handleToggleSelectAll = (checked) => {
    if (checked) setSelectedIds(new Set(dueTransactions.map(t => t.id)));
    else setSelectedIds(new Set());
  };

  const handleToggleSelect = (id, checked) => {
    const newSelected = new Set(selectedIds);
    if (checked) newSelected.add(id); else newSelected.delete(id);
    setSelectedIds(newSelected);
  };

  const calculateNextRunDate = (currentDateStr, frequency) => {
    const date = new Date(currentDateStr);
    switch (frequency?.toLowerCase()) {
      case 'daily': return addDays(date, 1);
      case 'weekly': return addWeeks(date, 1);
      case 'monthly': return addMonths(date, 1);
      case 'quarterly': return addQuarters(date, 1);
      case 'yearly': return addYears(date, 1);
      default: return addMonths(date, 1);
    }
  };

  const processSelected = async () => {
    if (selectedIds.size === 0) return;
    setProcessingState('processing'); setProgress(0);
    const successList = []; const failedList = [];
    const toProcess = dueTransactions.filter(t => selectedIds.has(t.id));
    const total = toProcess.length;
    const { data: userData } = await supabase.auth.getUser();
    const userId = userData?.user?.id;

    for (let i = 0; i < total; i++) {
      const rt = toProcess[i];
      try {
        let unitIds = [];
        if (rt.target_type === 'all') {
          const { data: owners, error: ownerErr } = await supabase.from('owners').select('id').eq('association_id', clientId).eq('status', 'active');
          if (ownerErr) throw new Error('Failed to fetch owners');
          unitIds = owners.map(o => o.id);
        } else {
          unitIds = rt.target_ids || [];
        }
        if (unitIds.length === 0) throw new Error('No target properties found.');

        const todayStr = new Date().toISOString().split('T')[0];
        const txTypeStr = (rt.transaction_type || 'charge').toLowerCase();
        const debitCredit = txTypeStr.includes('charge') ? 'debit' : 'credit';

        const transactionsToInsert = unitIds.map(uid => ({
          unit_id: uid, transaction_date: todayStr,
          description: `Auto: ${rt.name}`, amount: rt.amount,
          debit_credit: debitCredit, transaction_type: txTypeStr.charAt(0).toUpperCase() + txTypeStr.slice(1),
          category: 'Recurring', status: 'active', created_by: userId
        }));

        const chunkSize = 100;
        for (let j = 0; j < transactionsToInsert.length; j += chunkSize) {
          const chunk = transactionsToInsert.slice(j, j + chunkSize);
          const { error: txErr } = await supabase.from('owner_ledger_entries').insert(chunk.map(t => ({
            association_id: clientId, owner_id: t.unit_id, date: t.transaction_date,
            description: t.description, debit: t.debit_credit === 'debit' ? t.amount : 0,
            credit: t.debit_credit === 'credit' ? t.amount : 0,
            transaction_type: t.transaction_type, created_by: t.created_by
          })));
          if (txErr) throw new Error(`Failed to insert ledger entries: ${txErr.message}`);
        }

        const nextDate = calculateNextRunDate(rt.next_run_date || todayStr, rt.frequency);
        const { error: updateErr } = await supabase.from('recurring_transactions')
          .update({ last_applied_date: todayStr, next_run_date: nextDate.toISOString().split('T')[0] })
          .eq('id', rt.id);
        if (updateErr) throw new Error(`Failed to update next run date: ${updateErr.message}`);
        successList.push(rt);
      } catch (err) {
        console.error(`Error processing ${rt.name}:`, err);
        failedList.push({ item: rt, error: err.message });
      }
      setProgress(((i + 1) / total) * 100);
    }

    setResults({ success: successList, failed: failedList });
    setProcessingState('complete');
    if (failedList.length === 0) toast({ title: 'Success', description: `Processed ${successList.length} recurring transactions.` });
    else toast({ variant: 'destructive', title: 'Completed with Errors', description: `${successList.length} succeeded, ${failedList.length} failed.` });
    if (onProcessed) onProcessed();
  };

  const handleClose = () => { if (processingState === 'processing') return; onOpenChange(false); };
  const formatCurrency = (val) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(val);

  return (
    <Dialog open={open} onOpenChange={handleClose}>
      <DialogContent className="sm:max-w-[700px] p-0 overflow-hidden">
        <DialogHeader className="p-6 pb-4 border-b bg-muted/50">
          <DialogTitle className="text-xl font-bold flex items-center gap-2">
            <RefreshCw className="w-5 h-5 text-primary" /> Process Due Recurring Transactions
          </DialogTitle>
          <DialogDescription>Review and generate ledger entries for transactions scheduled on or before today.</DialogDescription>
        </DialogHeader>
        <div className="p-6">
          {processingState === 'idle' && (
            <>
              {loading ? (
                <div className="flex flex-col items-center justify-center py-12">
                  <Loader2 className="h-8 w-8 animate-spin text-primary mb-4" />
                  <p className="text-sm text-muted-foreground font-medium">Checking for due transactions...</p>
                </div>
              ) : dueTransactions.length === 0 ? (
                <div className="flex flex-col items-center justify-center py-16 text-center">
                  <div className="bg-emerald-100 p-3 rounded-full mb-4"><CheckCircle2 className="h-8 w-8 text-emerald-600" /></div>
                  <h3 className="text-lg font-semibold mb-1">All Caught Up!</h3>
                  <p className="text-muted-foreground">No recurring transactions currently due.</p>
                </div>
              ) : (
                <div className="space-y-4">
                  <div className="rounded-md border overflow-hidden">
                    <ScrollArea className="h-[300px]">
                      <Table>
                        <TableHeader className="bg-muted sticky top-0 z-10 shadow-sm">
                          <TableRow>
                            <TableHead className="w-[50px] text-center">
                              <Checkbox checked={selectedIds.size === dueTransactions.length && dueTransactions.length > 0} onCheckedChange={handleToggleSelectAll} />
                            </TableHead>
                            <TableHead className="font-semibold">Name / Description</TableHead>
                            <TableHead className="font-semibold">Amount</TableHead>
                            <TableHead className="font-semibold">Due Date</TableHead>
                            <TableHead className="font-semibold">Target</TableHead>
                          </TableRow>
                        </TableHeader>
                        <TableBody>
                          {dueTransactions.map((tx) => (
                            <TableRow key={tx.id} className="hover:bg-muted/50 transition-colors">
                              <TableCell className="text-center"><Checkbox checked={selectedIds.has(tx.id)} onCheckedChange={(c) => handleToggleSelect(tx.id, c)} /></TableCell>
                              <TableCell className="font-medium">{tx.name}</TableCell>
                              <TableCell className="text-muted-foreground">{formatCurrency(tx.amount)}</TableCell>
                              <TableCell><span className="inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-amber-100 text-amber-800">{format(new Date(tx.next_run_date), 'MMM d, yyyy')}</span></TableCell>
                              <TableCell className="text-muted-foreground text-sm capitalize">{tx.target_type === 'all' ? 'All Units' : `${tx.target_ids?.length || 0} Units`}</TableCell>
                            </TableRow>
                          ))}
                        </TableBody>
                      </Table>
                    </ScrollArea>
                  </div>
                  <Alert className="bg-primary/5 border-primary/10">
                    <PlayCircle className="h-4 w-4 text-primary" />
                    <AlertTitle className="font-semibold">Ready to Process</AlertTitle>
                    <AlertDescription>{selectedIds.size} transaction(s) selected. This will generate ledger charges and update next run dates.</AlertDescription>
                  </Alert>
                </div>
              )}
            </>
          )}

          {processingState === 'processing' && (
            <div className="py-12 px-6 flex flex-col items-center justify-center space-y-6">
              <Loader2 className="h-12 w-12 animate-spin text-primary" />
              <div className="w-full max-w-md space-y-2 text-center">
                <h3 className="text-lg font-semibold">Processing Transactions...</h3>
                <p className="text-sm text-muted-foreground">Please do not close this window.</p>
                <Progress value={progress} className="h-2 w-full mt-4" />
                <p className="text-xs text-muted-foreground font-medium text-right">{Math.round(progress)}%</p>
              </div>
            </div>
          )}

          {processingState === 'complete' && (
            <div className="space-y-6 py-4">
              <div className="flex items-center justify-center gap-4 mb-8">
                <div className="flex flex-col items-center justify-center p-4 bg-emerald-50 rounded-xl border border-emerald-100 w-32">
                  <span className="text-3xl font-bold text-emerald-600">{results.success.length}</span>
                  <span className="text-xs font-medium text-emerald-800 uppercase tracking-wider mt-1">Success</span>
                </div>
                <div className="flex flex-col items-center justify-center p-4 bg-destructive/5 rounded-xl border border-destructive/10 w-32">
                  <span className="text-3xl font-bold text-destructive">{results.failed.length}</span>
                  <span className="text-xs font-medium text-destructive uppercase tracking-wider mt-1">Failed</span>
                </div>
              </div>
              {results.failed.length > 0 && (
                <Alert variant="destructive">
                  <AlertCircle className="h-4 w-4" />
                  <AlertTitle>Errors Occurred</AlertTitle>
                  <AlertDescription>
                    <ul className="list-disc pl-5 mt-2 space-y-1 text-sm">
                      {results.failed.map((f, i) => <li key={i}><strong>{f.item.name}:</strong> {f.error}</li>)}
                    </ul>
                  </AlertDescription>
                </Alert>
              )}
              {results.success.length > 0 && results.failed.length === 0 && (
                <div className="text-center p-6 bg-emerald-50 rounded-lg border border-emerald-100">
                  <CheckCircle2 className="w-10 h-10 text-emerald-500 mx-auto mb-3" />
                  <h3 className="text-lg font-semibold text-emerald-900">All Done!</h3>
                  <p className="text-emerald-700 text-sm mt-1">All selected transactions were successfully applied.</p>
                </div>
              )}
            </div>
          )}
        </div>
        <DialogFooter className="p-6 border-t bg-muted/50">
          {processingState === 'idle' ? (
            <div className="flex justify-end gap-3 w-full">
              <Button variant="outline" onClick={handleClose}>Cancel</Button>
              <Button onClick={processSelected} disabled={selectedIds.size === 0 || loading || dueTransactions.length === 0}>Process Selected</Button>
            </div>
          ) : processingState === 'complete' ? (
            <Button onClick={handleClose} className="w-full sm:w-auto">Close & Return</Button>
          ) : null}
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
