import { useEffect, useState, useCallback } from 'react';
import { Plus, ChevronRight, Trash2 } from 'lucide-react';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter,
} from '@/components/ui/dialog';
import {
  AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle,
  AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction,
} from '@/components/ui/alert-dialog';
import {
  Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@/components/ui/select';
import { api } from '@/api';
import { cn } from '@/lib/utils';
import BillsTableInner from '@/components/BillsTableInner';
import BillModal from '@/components/BillModal';

const VISIBILITY_OPTIONS = [
  { value: 'default', label: 'Default', description: 'Use the app default behavior for inactive bill history.' },
  { value: 'all',     label: 'Show all history', description: 'Show all historical tracker data for this inactive bill.' },
  { value: 'none',    label: 'Show no history', description: 'Hide historical tracker data for this inactive bill.' },
  { value: 'ranges',  label: 'Show only selected date ranges', description: 'Show history only for the ranges listed below.' },
];
const MONTH_OPTIONS = [
  ['1', 'Jan'], ['2', 'Feb'], ['3', 'Mar'], ['4', 'Apr'], ['5', 'May'], ['6', 'Jun'],
  ['7', 'Jul'], ['8', 'Aug'], ['9', 'Sep'], ['10', 'Oct'], ['11', 'Nov'], ['12', 'Dec'],
];

// BillModal is imported from @/components/BillModal

function blankRange() {
  const year = String(new Date().getFullYear());
  return {
    _key: `new-${Date.now()}-${Math.random().toString(16).slice(2)}`,
    start_year: year,
    start_month: String(new Date().getMonth() + 1),
    end_year: '',
    end_month: '',
    label: '',
  };
}

function normalizeRange(range) {
  return {
    ...range,
    _key: range._key || String(range.id),
    start_year: String(range.start_year ?? ''),
    start_month: String(range.start_month ?? ''),
    end_year: range.end_year == null ? '' : String(range.end_year),
    end_month: range.end_month == null ? '' : String(range.end_month),
    label: range.label || '',
  };
}

function rangePayload(range) {
  return {
    start_year: parseInt(range.start_year, 10),
    start_month: parseInt(range.start_month, 10),
    end_year: range.end_year ? parseInt(range.end_year, 10) : null,
    end_month: range.end_month ? parseInt(range.end_month, 10) : null,
    label: range.label?.trim() || null,
  };
}

function validateRange(range) {
  const payload = rangePayload(range);
  if (!Number.isInteger(payload.start_year) || payload.start_year < 2000 || payload.start_year > 2100) {
    return 'Start year must be between 2000 and 2100.';
  }
  if (!Number.isInteger(payload.start_month) || payload.start_month < 1 || payload.start_month > 12) {
    return 'Start month must be between 1 and 12.';
  }
  if ((payload.end_year == null) !== (payload.end_month == null)) {
    return 'End year and end month must both be provided or both left blank.';
  }
  if (payload.end_year != null) {
    if (payload.end_year < 2000 || payload.end_year > 2100) {
      return 'End year must be between 2000 and 2100.';
    }
    if (payload.end_month < 1 || payload.end_month > 12) {
      return 'End month must be between 1 and 12.';
    }
    if ((payload.end_year * 12 + payload.end_month) < (payload.start_year * 12 + payload.start_month)) {
      return 'Range end must be on or after the start.';
    }
  }
  return null;
}

function HistoryVisibilityDialog({ bill, onClose, onSaved }) {
  const [visibility, setVisibility] = useState(bill?.history_visibility || 'default');
  const [ranges, setRanges] = useState([]);
  const [deletedIds, setDeletedIds] = useState([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    let mounted = true;
    setLoading(true);
    api.billHistoryRanges(bill.id)
      .then(data => {
        if (!mounted) return;
        setVisibility(data.history_visibility || bill.history_visibility || 'default');
        setRanges((data.ranges || []).map(normalizeRange));
      })
      .catch(err => {
        toast.error(err.message || 'Failed to load history visibility.');
        onClose();
      })
      .finally(() => mounted && setLoading(false));
    return () => { mounted = false; };
  }, [bill, onClose]);

  const updateRange = (key, patch) => {
    setRanges(prev => prev.map(r => r._key === key ? { ...r, ...patch } : r));
  };

  const deleteRange = (range) => {
    if (range.id) setDeletedIds(prev => [...prev, range.id]);
    setRanges(prev => prev.filter(r => r._key !== range._key));
  };

  const save = async () => {
    if (visibility === 'ranges') {
      if (ranges.length === 0) {
        toast.error('Add at least one date range or choose another visibility option.');
        return;
      }
      const invalid = ranges.map(validateRange).find(Boolean);
      if (invalid) {
        toast.error(invalid);
        return;
      }
    }

    setSaving(true);
    try {
      await api.updateBill(bill.id, { history_visibility: visibility });
      for (const id of deletedIds) {
        await api.deleteBillHistoryRange(bill.id, id);
      }
      if (visibility === 'ranges') {
        for (const range of ranges) {
          const payload = rangePayload(range);
          if (range.id) {
            await api.updateBillHistoryRange(bill.id, range.id, payload);
          } else {
            await api.createBillHistoryRange(bill.id, payload);
          }
        }
      }
      toast.success('History visibility saved.');
      onSaved();
      onClose();
    } catch (err) {
      toast.error(err.message || 'Failed to save history visibility.');
    } finally {
      setSaving(false);
    }
  };

  return (
    <Dialog open onOpenChange={v => { if (!v && !saving) onClose(); }}>
      <DialogContent className="sm:max-w-4xl border-border/60 bg-card/95 backdrop-blur-xl">
        <DialogHeader>
          <DialogTitle className="text-base font-semibold tracking-tight">
            History Visibility: {bill.name}
          </DialogTitle>
        </DialogHeader>

        {loading ? (
          <div className="py-12 text-center text-sm text-muted-foreground">Loading history visibility...</div>
        ) : (
          <div className="space-y-5">
            <div className="rounded-lg border border-border/60 bg-muted/25 p-4">
              <p className="text-sm font-medium">Inactive bill history</p>
              <p className="mt-1 text-xs text-muted-foreground">
                Choose whether this inactive bill should appear in historical tracker views. Active bill behavior is unchanged.
              </p>
            </div>

            <div className="grid gap-3 md:grid-cols-2">
              {VISIBILITY_OPTIONS.map(option => (
                <label
                  key={option.value}
                  className={cn(
                    'flex cursor-pointer gap-3 rounded-lg border px-4 py-3 transition-colors',
                    visibility === option.value
                      ? 'border-primary/40 bg-primary/10'
                      : 'border-border/60 bg-muted/15 hover:bg-muted/30'
                  )}
                >
                  <input
                    type="radio"
                    name="history_visibility"
                    value={option.value}
                    checked={visibility === option.value}
                    onChange={() => setVisibility(option.value)}
                    className="mt-1 h-4 w-4 accent-primary"
                  />
                  <span>
                    <span className="block text-sm font-medium">{option.label}</span>
                    <span className="mt-0.5 block text-xs text-muted-foreground">{option.description}</span>
                  </span>
                </label>
              ))}
            </div>

            {visibility === 'ranges' && (
              <div className="space-y-3">
                <div className="flex items-center justify-between">
                  <div>
                    <p className="text-sm font-medium">Selected date ranges</p>
                    <p className="text-xs text-muted-foreground">End month/year are optional for open-ended ranges.</p>
                  </div>
                  <Button type="button" size="sm" variant="outline" onClick={() => setRanges(prev => [...prev, blankRange()])}>
                    <Plus className="h-4 w-4" />
                    Add range
                  </Button>
                </div>

                {ranges.length === 0 ? (
                  <div className="rounded-lg border border-dashed border-border px-4 py-8 text-center text-sm text-muted-foreground">
                    No ranges yet. Add a range to use selected history.
                  </div>
                ) : (
                  <div className="space-y-2">
                    {ranges.map(range => (
                      <div key={range._key} className="grid gap-2 rounded-lg border border-border/60 bg-background/40 p-3 md:grid-cols-[1fr_120px_1fr_120px_1.2fr_auto] md:items-end">
                        <div className="space-y-1.5">
                          <Label className="text-[10px] uppercase tracking-wider text-muted-foreground">Start year</Label>
                          <Input
                            type="number"
                            min="2000"
                            max="2100"
                            value={range.start_year}
                            onChange={e => updateRange(range._key, { start_year: e.target.value })}
                            className="h-8"
                          />
                        </div>
                        <div className="space-y-1.5">
                          <Label className="text-[10px] uppercase tracking-wider text-muted-foreground">Start month</Label>
                          <Select value={range.start_month} onValueChange={v => updateRange(range._key, { start_month: v })}>
                            <SelectTrigger className="h-8">
                              <SelectValue />
                            </SelectTrigger>
                            <SelectContent>
                              {MONTH_OPTIONS.map(([value, label]) => <SelectItem key={value} value={value}>{label}</SelectItem>)}
                            </SelectContent>
                          </Select>
                        </div>
                        <div className="space-y-1.5">
                          <Label className="text-[10px] uppercase tracking-wider text-muted-foreground">End year</Label>
                          <Input
                            type="number"
                            min="2000"
                            max="2100"
                            placeholder="Open"
                            value={range.end_year}
                            onChange={e => updateRange(range._key, { end_year: e.target.value })}
                            className="h-8"
                          />
                        </div>
                        <div className="space-y-1.5">
                          <Label className="text-[10px] uppercase tracking-wider text-muted-foreground">End month</Label>
                          <Select value={range.end_month || 'open'} onValueChange={v => updateRange(range._key, { end_month: v === 'open' ? '' : v })}>
                            <SelectTrigger className="h-8">
                              <SelectValue />
                            </SelectTrigger>
                            <SelectContent>
                              <SelectItem value="open">Open</SelectItem>
                              {MONTH_OPTIONS.map(([value, label]) => <SelectItem key={value} value={value}>{label}</SelectItem>)}
                            </SelectContent>
                          </Select>
                        </div>
                        <div className="space-y-1.5">
                          <Label className="text-[10px] uppercase tracking-wider text-muted-foreground">Label</Label>
                          <Input
                            value={range.label}
                            onChange={e => updateRange(range._key, { label: e.target.value })}
                            placeholder="Optional"
                            className="h-8"
                          />
                        </div>
                        <Button
                          type="button"
                          variant="ghost"
                          size="icon"
                          className="h-8 w-8 text-destructive hover:bg-destructive/10 hover:text-destructive"
                          onClick={() => deleteRange(range)}
                          aria-label="Delete history range"
                        >
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            )}
          </div>
        )}

        <DialogFooter className="mt-2">
          <Button type="button" variant="ghost" disabled={saving} onClick={onClose} className="text-xs">
            Cancel
          </Button>
          <Button type="button" disabled={saving || loading} onClick={save} className="text-xs">
            {saving ? 'Saving...' : 'Save History Visibility'}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// ── Bills Page ─────────────────────────────────────────────────────────────
export default function BillsPage() {
  const [bills,        setBills]       = useState([]);
  const [categories,   setCategories]  = useState([]);
  const [loading,      setLoading]     = useState(true);
  const [showInactive, setShowInactive] = useState(false);

  // modal state: null = closed, { bill: null } = add new, { bill: {...} } = edit
  const [modal,      setModal]      = useState(null);
  // Bill pending deactivation confirmation (AlertDialog replaces window.confirm)
  const [deactivate, setDeactivate] = useState(null);
  const [deleteTarget, setDeleteTarget] = useState(null);
  const [deleteConfirmed, setDeleteConfirmed] = useState(false);
  const [deleteBusy, setDeleteBusy] = useState(false);
  const [historyTarget, setHistoryTarget] = useState(null);

  const load = useCallback(async () => {
    try {
      const [billsRes, catRes] = await Promise.all([
        api.allBills(),
        api.categories(),
      ]);
      setBills(billsRes  || []);
      setCategories(catRes || []);
    } catch (err) {
      toast.error(err.message);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { load(); }, [load]);

  async function handleEdit(billId) {
    try {
      const bill = await api.bill(billId);
      setModal({ bill });
    } catch (err) {
      toast.error(err.message);
    }
  }

  function handleToggle(bill) {
    if (bill.active) {
      // Prompt confirmation before deactivating
      setDeactivate(bill);
    } else {
      doToggle(bill);
    }
  }

  async function doToggle(bill) {
    if (!bill) return;
    try {
      await api.updateBill(bill.id, { active: bill.active ? 0 : 1 });
      toast.success(bill.active ? 'Bill deactivated' : 'Bill activated');
      load();
    } catch (err) {
      toast.error(err.message);
    }
  }

  function handleDeleteRequest(bill) {
    setDeleteConfirmed(false);
    setDeleteTarget(bill);
  }

  async function handleDeleteConfirmed() {
    if (!deleteTarget || !deleteConfirmed) return;
    setDeleteBusy(true);
    try {
      const bill = deleteTarget;
      await api.deleteBill(bill.id);
      setBills(prev => prev.filter(b => b.id !== bill.id));
      toast.success(`"${bill.name}" deleted permanently`);
      setDeleteTarget(null);
      setDeleteConfirmed(false);
      load();
    } catch (err) {
      toast.error(err.message || 'Failed to delete bill');
    } finally {
      setDeleteBusy(false);
    }
  }

  async function handleDeleteAlternative() {
    if (!deleteTarget) return;
    const bill = deleteTarget;
    setDeleteTarget(null);
    setDeleteConfirmed(false);
    await doToggle(bill);
  }

  const active   = bills.filter(b => b.active);
  const inactive = bills.filter(b => !b.active);

  return (
    <div className="space-y-6">

      {/* ── Header ── */}
      <div className="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <p className="text-[11px] font-semibold uppercase tracking-[0.15em] text-muted-foreground mb-0.5">
            Manage
          </p>
          <h1 className="text-2xl font-bold tracking-tight">Bills</h1>
          <p className="text-xs text-muted-foreground mt-0.5">
            {active.length} active
            {inactive.length > 0 && (
              <span className="text-muted-foreground/50"> · {inactive.length} inactive</span>
            )}
          </p>
        </div>

        <Button
          onClick={() => setModal({ bill: null })}
          className="h-9 px-4 gap-2 text-sm font-medium"
        >
          <Plus className="h-4 w-4" />
          Add Bill
        </Button>
      </div>

      {/* ── Active Bills ── */}
      <div className="rounded-xl border border-border overflow-hidden bg-card">
        <div className="flex flex-col gap-3 px-6 py-3 bg-muted/30 border-b border-border sm:flex-row sm:items-center sm:justify-between">
          <span className="text-[11px] font-bold uppercase tracking-[0.12em] text-muted-foreground">
            Active Bills
          </span>
          <span className="text-xs font-mono text-muted-foreground">{active.length}</span>
        </div>

        {loading ? (
          <div className="py-16 text-center text-sm text-muted-foreground animate-pulse">
            Loading bills…
          </div>
        ) : active.length === 0 ? (
          <div className="py-16 text-center text-sm text-muted-foreground">
            No active bills.{' '}
            <button
              onClick={() => setModal({ bill: null })}
              className="underline underline-offset-4 hover:text-foreground transition-colors"
            >
              Add your first bill
            </button>
          </div>
        ) : (
          <BillsTableInner
            bills={active}
            onEdit={handleEdit}
            onToggle={handleToggle}
            onDelete={handleDeleteRequest}
          />
        )}
      </div>

      {/* ── Inactive Bills ── */}
      {!loading && inactive.length > 0 && (
        <div className="space-y-3">

          <button
            onClick={() => setShowInactive(v => !v)}
            className="flex items-center gap-2 text-xs text-muted-foreground hover:text-foreground transition-colors"
          >
            <ChevronRight className={cn(
              'h-3 w-3 transition-transform duration-200',
              showInactive && 'rotate-90',
            )} />
            <span className="uppercase tracking-[0.08em]">
              {inactive.length} inactive {inactive.length === 1 ? 'bill' : 'bills'}
            </span>
          </button>

          {showInactive && (
            <div className="rounded-xl border border-border overflow-hidden bg-card">
              <div className="flex flex-col gap-3 px-6 py-3 bg-muted/30 border-b border-border sm:flex-row sm:items-center sm:justify-between">
                <span className="text-[11px] font-bold uppercase tracking-[0.12em] text-muted-foreground">
                  Inactive Bills
                </span>
                <span className="text-xs font-mono text-muted-foreground">{inactive.length}</span>
              </div>
              <BillsTableInner
                bills={inactive}
                onEdit={handleEdit}
                onToggle={handleToggle}
                onDelete={handleDeleteRequest}
                onHistory={setHistoryTarget}
              />
            </div>
          )}

        </div>
      )}

      {/* ── Bill Modal ── */}
      {modal && (
        <BillModal
          bill={modal.bill}
          categories={categories}
          onClose={() => setModal(null)}
          onSave={load}
        />
      )}

      {historyTarget && (
        <HistoryVisibilityDialog
          bill={historyTarget}
          onClose={() => setHistoryTarget(null)}
          onSaved={load}
        />
      )}

      {/* ── Deactivate confirmation (replaces window.confirm) ── */}
      <AlertDialog open={!!deactivate} onOpenChange={open => { if (!open) setDeactivate(null); }}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Deactivate "{deactivate?.name}"?</AlertDialogTitle>
            <AlertDialogDescription>
              This bill will be hidden from the tracker. You can reactivate it at any time.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onClick={() => setDeactivate(null)}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
              onClick={() => { const b = deactivate; setDeactivate(null); doToggle(b); }}
            >
              Deactivate
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* ── Permanent delete confirmation ── */}
      <AlertDialog
        open={!!deleteTarget}
        onOpenChange={open => {
          if (!open && !deleteBusy) {
            setDeleteTarget(null);
            setDeleteConfirmed(false);
          }
        }}
      >
        <AlertDialogContent className="max-w-lg">
          <AlertDialogHeader>
            <AlertDialogTitle>Delete "{deleteTarget?.name}" permanently?</AlertDialogTitle>
            <AlertDialogDescription>
              This permanently deletes the bill and all data for this bill, including payments,
              monthly history, notes, and history ranges. This cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>

          <div className="rounded-lg border border-destructive/25 bg-destructive/10 px-4 py-3 text-sm text-destructive">
            Deactivate is the safer option if you only want to hide this bill from active tracking.
          </div>

          <label className="flex items-start gap-3 rounded-lg border border-border bg-muted/25 px-4 py-3 text-sm">
            <input
              type="checkbox"
              checked={deleteConfirmed}
              onChange={e => setDeleteConfirmed(e.target.checked)}
              disabled={deleteBusy}
              className="mt-0.5 h-4 w-4 rounded border-input bg-input accent-destructive"
            />
            <span>I understand this deletes all data for this bill and cannot be undone.</span>
          </label>

          <AlertDialogFooter className="sm:justify-between">
            <AlertDialogCancel
              disabled={deleteBusy}
              className="border border-input bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground"
            >
              Cancel
            </AlertDialogCancel>
            <div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
              <Button
                type="button"
                variant="outline"
                disabled={deleteBusy}
                onClick={handleDeleteAlternative}
              >
                {deleteTarget?.active ? 'Deactivate instead' : 'Activate instead'}
              </Button>
              <Button
                type="button"
                variant="destructive"
                disabled={!deleteConfirmed || deleteBusy}
                onClick={handleDeleteConfirmed}
              >
                {deleteBusy ? 'Deleting…' : 'Delete permanently'}
              </Button>
            </div>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

    </div>
  );
}
