import { useState } from 'react';
import { ChevronDown } 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 {
  Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@/components/ui/select';
import { api } from '@/api';
import { cn } from '@/lib/utils';

function getOrdinalSuffix(day) {
  if (day > 3 && day < 21) return 'th';
  switch (day % 10) {
    case 1: return 'st';
    case 2: return 'nd';
    case 3: return 'rd';
    default: return 'th';
  }
}

// Radix Select crashes on empty string value
const CAT_NONE = 'none';

const DEBT_KEYWORDS = ['credit', 'loan', 'mortgage', 'housing', 'debt'];
const SNOWBALL_KEYWORDS = ['credit', 'loan', 'debt'];

function isDebtCat(categories, catId) {
  if (!catId || catId === CAT_NONE) return false;
  const cat = categories.find(c => String(c.id) === catId);
  return cat ? DEBT_KEYWORDS.some(kw => cat.name.toLowerCase().includes(kw)) : false;
}
function isSnowballCat(categories, catId) {
  if (!catId || catId === CAT_NONE) return false;
  const cat = categories.find(c => String(c.id) === catId);
  return cat ? SNOWBALL_KEYWORDS.some(kw => cat.name.toLowerCase().includes(kw)) : false;
}

export default function BillModal({ bill, categories, onClose, onSave }) {
  const isNew = !bill;

  const [name,           setName]         = useState(bill?.name            || '');
  const [categoryId,     setCategoryId]   = useState(bill?.category_id ? String(bill.category_id) : CAT_NONE);
  const [dueDay,         setDueDay]       = useState(String(bill?.due_day   || ''));
  const [expectedAmount, setExpected]     = useState(String(bill?.expected_amount || ''));
  const [interestRate,   setInterestRate] = useState(bill?.interest_rate == null ? '' : String(bill.interest_rate));
  const [billingCycle,   setCycle]        = useState(bill?.billing_cycle    || 'monthly');
  const [cycleType,      setCycleType]    = useState(bill?.cycle_type      || 'monthly');
  const [cycleDay,       setCycleDay]     = useState(bill?.cycle_day       || '1');
  const [autopay,        setAutopay]      = useState(!!bill?.autopay_enabled);
  const [has2fa,         setHas2fa]       = useState(!!bill?.has_2fa);
  const [website,        setWebsite]      = useState(bill?.website          || '');
  const [username,       setUsername]     = useState(bill?.username          || '');
  const [accountInfo,    setAccountInfo]  = useState(bill?.account_info     || '');
  const [notes,          setNotes]        = useState(bill?.notes            || '');
  const [currentBalance, setCurrentBalance] = useState(bill?.current_balance == null ? '' : String(bill.current_balance));
  const [minimumPayment, setMinimumPayment] = useState(bill?.minimum_payment == null ? '' : String(bill.minimum_payment));
  const [snowballInclude, setSnowballInclude] = useState(!!bill?.snowball_include);
  const [snowballExempt, setSnowballExempt] = useState(!!bill?.snowball_exempt);
  const [showDebtSection, setShowDebtSection] = useState(
    () => isDebtCat(categories, bill?.category_id ? String(bill.category_id) : CAT_NONE)
      || !!bill?.snowball_include
      || !!bill?.snowball_exempt
      || bill?.current_balance != null
      || bill?.minimum_payment != null
  );
  const [busy,           setBusy]         = useState(false);
  const [errors,         setErrors]       = useState({});

  const isDebtCategory = isDebtCat(categories, categoryId);
  const isSnowballCategory = isSnowballCat(categories, categoryId);
  const showOnSnowball = snowballInclude || (isSnowballCategory && !snowballExempt);

  const validateName = (val) => {
    if (!val || val.trim() === '') return 'Name is required';
    if (val.trim().length < 2) return 'Name must be at least 2 characters';
    return '';
  };

  const validateDueDay = (val) => {
    if (!val || val.trim() === '') return 'Due day is required';
    const num = parseInt(val, 10);
    if (isNaN(num) || num < 1 || num > 31) return 'Due day must be between 1 and 31';
    return '';
  };

  const validateExpectedAmount = (val) => {
    if (val === '' || val === null) return '';
    const num = parseFloat(val);
    if (isNaN(num) || num < 0) return 'Amount must be a positive number';
    return '';
  };

  const validateInterestRate = (val) => {
    if (val === '' || val === null) return '';
    const num = parseFloat(val);
    if (isNaN(num)) return 'Invalid number';
    if (num < 0 || num > 100) return 'Interest rate must be between 0 and 100';
    return '';
  };

  const validateCurrentBalance = (val) => {
    if (val === '' || val === null) return '';
    const num = parseFloat(val);
    if (isNaN(num) || num < 0) return 'Balance must be a non-negative number';
    return '';
  };

  const validateMinimumPayment = (val) => {
    if (val === '' || val === null) return '';
    const num = parseFloat(val);
    if (isNaN(num) || num < 0) return 'Min payment must be a non-negative number';
    return '';
  };

  const validateForm = () => {
    const newErrors = {
      name: validateName(name),
      dueDay: validateDueDay(dueDay),
      expectedAmount: validateExpectedAmount(expectedAmount),
      interestRate: validateInterestRate(interestRate),
      currentBalance: validateCurrentBalance(currentBalance),
      minimumPayment: validateMinimumPayment(minimumPayment),
    };
    setErrors(newErrors);
    return Object.values(newErrors).every(err => err === '');
  };

  const handleBlur = (field, validator) => {
    setErrors(prev => ({ ...prev, [field]: validator(
      field === 'name' ? name :
      field === 'dueDay' ? dueDay :
      field === 'expectedAmount' ? expectedAmount :
      interestRate
    )}));
  };

  const handleCategoryChange = (val) => {
    setCategoryId(val);
    if (isDebtCat(categories, val)) {
      setShowDebtSection(true);
    } else {
      setSnowballExempt(false);
    }
  };

  const handleSnowballVisibilityChange = (checked) => {
    if (checked) {
      setSnowballExempt(false);
      setSnowballInclude(!isSnowballCategory);
    } else {
      setSnowballInclude(false);
      setSnowballExempt(isSnowballCategory);
    }
  };

  async function handleSubmit(e) {
    e.preventDefault();

    if (!validateForm()) {
      toast.error('Please fix the form errors before saving.');
      return;
    }

    const parsedDueDay = Number(dueDay);
    if (!Number.isInteger(parsedDueDay) || parsedDueDay < 1 || parsedDueDay > 31) {
      toast.error('Due day must be a whole number from 1 to 31.');
      return;
    }

    const trimmedInterestRate = interestRate.trim();
    const parsedInterestRate = trimmedInterestRate === '' ? null : Number(trimmedInterestRate);
    if (parsedInterestRate !== null && (!Number.isFinite(parsedInterestRate) || parsedInterestRate < 0 || parsedInterestRate > 100)) {
      toast.error('Interest rate must be blank or a number from 0 to 100.');
      return;
    }

    const data = {
      name:              name.trim(),
      category_id:       categoryId === CAT_NONE ? null : parseInt(categoryId, 10),
      due_day:           parsedDueDay,
      expected_amount:   parseFloat(expectedAmount) || 0,
      interest_rate:     parsedInterestRate,
      billing_cycle:     billingCycle,
      cycle_type:        cycleType,
      cycle_day:         cycleDay,
      autopay_enabled:   autopay,
      has_2fa:           has2fa,
      website:           website     || null,
      username:          username    || null,
      account_info:      accountInfo || null,
      notes:             notes       || null,
      current_balance:   currentBalance === '' ? null : parseFloat(currentBalance),
      minimum_payment:   minimumPayment === '' ? null : parseFloat(minimumPayment),
      snowball_include:  snowballInclude,
      snowball_exempt:   snowballExempt,
    };
    setBusy(true);
    try {
      if (isNew) {
        await api.createBill(data);
        toast.success('Bill added');
      } else {
        await api.updateBill(bill.id, data);
        toast.success('Bill updated');
      }
      onSave();
      onClose();
    } catch (err) {
      toast.error(err.message);
    } finally {
      setBusy(false);
    }
  }

  const inp = 'bg-background/50 border-border/60 h-9 text-sm w-full';

  return (
    <Dialog open onOpenChange={v => { if (!v) onClose(); }}>
      <DialogContent className="sm:max-w-2xl border-border/60 bg-card/95 backdrop-blur-xl">
        <DialogHeader>
          <DialogTitle className="text-base font-semibold tracking-tight">
            {isNew ? 'Add Bill' : 'Edit Bill'}
          </DialogTitle>
        </DialogHeader>

        <form id="bill-modal-form" onSubmit={handleSubmit}>
          <div className="grid gap-x-5 gap-y-4 py-2 sm:grid-cols-2">

            {/* Name */}
            <div className="col-span-2 space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Name *</Label>
              <Input
                className={cn(inp, errors.name && 'border-red-500 focus-visible:ring-red-500')}
                placeholder="e.g. Electricity"
                value={name}
                onChange={e => {
                  setName(e.target.value);
                  setTimeout(() => setErrors(prev => ({ ...prev, name: validateName(e.target.value) })), 300);
                }}
                onBlur={() => handleBlur('name', validateName)}
                required
              />
              {errors.name && (
                <span className="text-[10px] text-red-500 font-medium">{errors.name}</span>
              )}
            </div>

            {/* Category */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Category</Label>
              <Select value={categoryId} onValueChange={handleCategoryChange}>
                <SelectTrigger className={cn(inp, 'w-full')}>
                  <SelectValue placeholder="— none —" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={CAT_NONE}>— none —</SelectItem>
                  {categories.map(c => (
                    <SelectItem key={c.id} value={String(c.id)}>{c.name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            {/* Due Day */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Due day of month *</Label>
              <Input
                className={cn(inp, errors.dueDay && 'border-red-500 focus-visible:ring-red-500')}
                type="number" min="1" max="31" required
                value={dueDay}
                onChange={e => {
                  setDueDay(e.target.value);
                  setTimeout(() => setErrors(prev => ({ ...prev, dueDay: validateDueDay(e.target.value) })), 300);
                }}
                onBlur={() => handleBlur('dueDay', validateDueDay)}
              />
              {errors.dueDay && (
                <span className="text-[10px] text-red-500 font-medium">{errors.dueDay}</span>
              )}
              <p className="text-[10px] text-muted-foreground/70">
                Enter the day of the month this bill is due.
              </p>
            </div>

            {/* Expected Amount */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Expected Amount ($)</Label>
              <Input
                className={cn(inp, 'font-mono', errors.expectedAmount && 'border-red-500 focus-visible:ring-red-500')}
                type="number" min="0" step="0.01" placeholder="0.00"
                value={expectedAmount}
                onChange={e => {
                  setExpected(e.target.value);
                  setTimeout(() => setErrors(prev => ({ ...prev, expectedAmount: validateExpectedAmount(e.target.value) })), 300);
                }}
                onBlur={() => handleBlur('expectedAmount', validateExpectedAmount)}
              />
              {errors.expectedAmount && (
                <span className="text-[10px] text-red-500 font-medium">{errors.expectedAmount}</span>
              )}
            </div>

            {/* Billing Cycle */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Billing Cycle</Label>
              <Select value={billingCycle} onValueChange={setCycle}>
                <SelectTrigger className={cn(inp, 'w-full')}>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="monthly">Monthly</SelectItem>
                  <SelectItem value="quarterly">Quarterly</SelectItem>
                  <SelectItem value="annually">Annually</SelectItem>
                  <SelectItem value="irregular">Irregular</SelectItem>
                </SelectContent>
              </Select>
            </div>

            {/* Cycle Type */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Cycle Type</Label>
              <Select value={cycleType} onValueChange={setCycleType}>
                <SelectTrigger className={cn(inp, 'w-full')}>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="monthly">Monthly</SelectItem>
                  <SelectItem value="weekly">Weekly</SelectItem>
                  <SelectItem value="biweekly">Biweekly</SelectItem>
                  <SelectItem value="quarterly">Quarterly</SelectItem>
                  <SelectItem value="annual">Annual</SelectItem>
                </SelectContent>
              </Select>
            </div>

            {/* Cycle Day */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Cycle Day</Label>
              {cycleType === 'monthly' ? (
                <Select value={cycleDay} onValueChange={setCycleDay}>
                  <SelectTrigger className={cn(inp, 'w-full')}>
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {[...Array(31)].map((_, i) => (
                      <SelectItem key={i+1} value={String(i+1)}>{i+1}{getOrdinalSuffix(i+1)}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              ) : cycleType === 'weekly' || cycleType === 'biweekly' ? (
                <Select value={cycleDay} onValueChange={setCycleDay}>
                  <SelectTrigger className={cn(inp, 'w-full')}>
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="monday">Monday</SelectItem>
                    <SelectItem value="tuesday">Tuesday</SelectItem>
                    <SelectItem value="wednesday">Wednesday</SelectItem>
                    <SelectItem value="thursday">Thursday</SelectItem>
                    <SelectItem value="friday">Friday</SelectItem>
                    <SelectItem value="saturday">Saturday</SelectItem>
                    <SelectItem value="sunday">Sunday</SelectItem>
                  </SelectContent>
                </Select>
              ) : (
                <Input
                  className={inp}
                  type="text"
                  placeholder="Day of period"
                  value={cycleDay}
                  onChange={e => setCycleDay(e.target.value)}
                />
              )}
              <p className="text-[10px] text-muted-foreground/70">
                {cycleType === 'monthly' ? 'Day of the month' :
                 cycleType === 'weekly' || cycleType === 'biweekly' ? 'Day of the week' :
                 'Day of the period'}
              </p>
            </div>

            {/* Debt / Snowball Details — collapsible */}
            <div className="col-span-2">
              <button
                type="button"
                onClick={() => setShowDebtSection(s => !s)}
                className="flex items-center gap-2 text-xs uppercase tracking-wider text-muted-foreground hover:text-foreground transition-colors w-full text-left py-1"
              >
                <ChevronDown
                  className={cn('h-3.5 w-3.5 transition-transform duration-150', !showDebtSection && '-rotate-90')}
                />
                Debt / Snowball Details
                {isSnowballCategory && (
                  <span className="ml-1 text-[9px] text-emerald-400 font-semibold tracking-normal normal-case">
                    · snowball auto-detected
                  </span>
                )}
                {!showOnSnowball && isSnowballCategory && (
                  <span className="ml-1 text-[9px] text-amber-400 font-semibold tracking-normal normal-case">
                    · exempt
                  </span>
                )}
              </button>

              {showDebtSection && (
                <div className="grid sm:grid-cols-2 gap-x-5 gap-y-4 mt-3 pt-3 border-t border-border/40">

                  {/* Interest Rate */}
                  <div className="space-y-1.5">
                    <Label className="text-xs uppercase tracking-wider text-muted-foreground">Interest rate (APR %)</Label>
                    <Input
                      className={cn(inp, 'font-mono', errors.interestRate && 'border-red-500 focus-visible:ring-red-500')}
                      type="number" min="0" max="100" step="0.01" placeholder="Optional"
                      value={interestRate}
                      onChange={e => {
                        setInterestRate(e.target.value);
                        setTimeout(() => setErrors(prev => ({ ...prev, interestRate: validateInterestRate(e.target.value) })), 300);
                      }}
                      onBlur={() => handleBlur('interestRate', validateInterestRate)}
                    />
                    {errors.interestRate && (
                      <span className="text-[10px] text-red-500 font-medium">{errors.interestRate}</span>
                    )}
                    <p className="text-[10px] text-muted-foreground/70">Enter 29.99 for 29.99%.</p>
                  </div>

                  {/* Current Balance */}
                  <div className="space-y-1.5">
                    <Label className="text-xs uppercase tracking-wider text-muted-foreground">Current Balance ($)</Label>
                    <Input
                      className={cn(inp, 'font-mono', errors.currentBalance && 'border-red-500 focus-visible:ring-red-500')}
                      type="number" min="0" step="0.01" placeholder="Optional"
                      value={currentBalance}
                      onChange={e => {
                        setCurrentBalance(e.target.value);
                        setTimeout(() => setErrors(prev => ({ ...prev, currentBalance: validateCurrentBalance(e.target.value) })), 300);
                      }}
                      onBlur={() => setErrors(prev => ({ ...prev, currentBalance: validateCurrentBalance(currentBalance) }))}
                    />
                    {errors.currentBalance && (
                      <span className="text-[10px] text-red-500 font-medium">{errors.currentBalance}</span>
                    )}
                    <p className="text-[10px] text-muted-foreground/70">Outstanding debt balance.</p>
                  </div>

                  {/* Minimum Payment */}
                  <div className="space-y-1.5">
                    <Label className="text-xs uppercase tracking-wider text-muted-foreground">Minimum Payment ($)</Label>
                    <Input
                      className={cn(inp, 'font-mono', errors.minimumPayment && 'border-red-500 focus-visible:ring-red-500')}
                      type="number" min="0" step="0.01" placeholder="Optional"
                      value={minimumPayment}
                      onChange={e => {
                        setMinimumPayment(e.target.value);
                        setTimeout(() => setErrors(prev => ({ ...prev, minimumPayment: validateMinimumPayment(e.target.value) })), 300);
                      }}
                      onBlur={() => setErrors(prev => ({ ...prev, minimumPayment: validateMinimumPayment(minimumPayment) }))}
                    />
                    {errors.minimumPayment && (
                      <span className="text-[10px] text-red-500 font-medium">{errors.minimumPayment}</span>
                    )}
                    <p className="text-[10px] text-muted-foreground/70">Required minimum monthly payment.</p>
                  </div>

                  {/* Include in Snowball */}
                  <div className="flex flex-col justify-end pb-1 space-y-1">
                    <label className="flex items-center gap-2.5 cursor-pointer group">
                      <input
                        type="checkbox"
                        checked={showOnSnowball}
                        onChange={e => handleSnowballVisibilityChange(e.target.checked)}
                        className="h-4 w-4 rounded border-border accent-emerald-500"
                      />
                      <span className="text-sm text-muted-foreground group-hover:text-foreground transition-colors">
                        Show on Debt Snowball
                      </span>
                    </label>
                    <p className="text-[10px] text-muted-foreground/70 pl-6">
                      Uncheck to exempt an auto-detected snowball bill, or check to include this bill manually.
                    </p>
                  </div>

                </div>
              )}
            </div>

            {/* Website */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Website</Label>
              <Input
                className={inp}
                placeholder="https://…"
                value={website}
                onChange={e => setWebsite(e.target.value)}
              />
            </div>

            {/* Username */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Username / Email</Label>
              <Input
                className={inp}
                value={username}
                onChange={e => setUsername(e.target.value)}
              />
            </div>

            {/* Account Info */}
            <div className="space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Account Info</Label>
              <Input
                className={inp}
                placeholder="Last 4 digits, account #…"
                value={accountInfo}
                onChange={e => setAccountInfo(e.target.value)}
              />
            </div>

            {/* Checkboxes */}
            <div className="space-y-2.5 flex flex-col justify-end">
              <label className="flex items-center gap-2.5 cursor-pointer group">
                <input
                  type="checkbox"
                  checked={autopay}
                  onChange={e => setAutopay(e.target.checked)}
                  className="h-4 w-4 rounded border-border accent-emerald-500"
                />
                <span className="text-sm text-muted-foreground group-hover:text-foreground transition-colors">
                  Autopay / Autodraft
                </span>
              </label>
              <label className="flex items-center gap-2.5 cursor-pointer group">
                <input
                  type="checkbox"
                  checked={has2fa}
                  onChange={e => setHas2fa(e.target.checked)}
                  className="h-4 w-4 rounded border-border accent-violet-500"
                />
                <span className="text-sm text-muted-foreground group-hover:text-foreground transition-colors">
                  Has 2FA
                </span>
              </label>
            </div>

            {/* Notes */}
            <div className="col-span-2 space-y-1.5">
              <Label className="text-xs uppercase tracking-wider text-muted-foreground">Notes</Label>
              <textarea
                rows={2}
                value={notes}
                onChange={e => setNotes(e.target.value)}
                className={cn(
                  'w-full rounded-md border border-border/60 bg-background/50 px-3 py-2',
                  'text-sm text-foreground placeholder:text-muted-foreground/50',
                  'resize-none outline-none focus:ring-1 focus:ring-ring transition-shadow',
                )}
                placeholder="Any additional notes…"
              />
            </div>

          </div>
        </form>

        <DialogFooter className="mt-2">
          <Button type="button" variant="ghost" disabled={busy} onClick={onClose} className="text-xs">
            Cancel
          </Button>
          <Button type="submit" form="bill-modal-form" disabled={busy} className="text-xs">
            {isNew ? 'Add Bill' : 'Save Changes'}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
