import { useId } from 'react';
import { motion } from 'framer-motion';
import { Wallet, CalendarClock, Sparkles, ArrowRight } from 'lucide-react';
import { cn, fmt, fmtDate } from '@/lib/utils';
import { asDollars } from '@/lib/money';
import { buildTimelineGeometry, daysUntilLabel, shortDate, splitUpcoming } from '@/lib/cashflowUtils';
import type { TrackerCashflow, CashflowTimelinePoint, SafeToSpendUpcoming, TimelineBill } from '@/types';

const CHART_W = 400;
const CHART_H = 96;

function TimelineChart({ timeline, positive }: { timeline: CashflowTimelinePoint[]; positive: boolean }) {
  const gradId = useId();
  const geo = buildTimelineGeometry(timeline, CHART_W, CHART_H);
  if (!geo) return null;

  const tone = positive ? '#10b981' : '#f43f5e'; // emerald-500 / rose-500

  return (
    <svg
      viewBox={`0 0 ${CHART_W} ${CHART_H}`}
      preserveAspectRatio="none"
      className="h-24 w-full"
      role="img"
      aria-label="Projected balance until next payday"
    >
      <defs>
        <linearGradient id={gradId} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={tone} stopOpacity="0.28" />
          <stop offset="100%" stopColor={tone} stopOpacity="0.02" />
        </linearGradient>
      </defs>

      {/* zero line — only meaningful when the projection dips negative */}
      {geo.points.some(p => p.balance < 0) && (
        <line
          x1="0" x2={CHART_W} y1={geo.zeroY} y2={geo.zeroY}
          stroke="#f43f5e" strokeOpacity="0.45" strokeDasharray="4 4" strokeWidth="1"
          vectorEffect="non-scaling-stroke"
        />
      )}

      <path d={geo.area} fill={`url(#${gradId})`} />
      <path
        d={geo.line}
        fill="none"
        stroke={tone}
        strokeWidth="2"
        strokeLinejoin="round"
        vectorEffect="non-scaling-stroke"
      />

      {/* bill-day markers */}
      {geo.points.filter(p => p.isDrop).map(p => (
        <circle key={p.date} cx={p.x} cy={p.y} r="3" fill={tone} stroke="var(--background, #18181b)" strokeWidth="1.5">
          <title>
            {`${fmtDate(p.date)} — ${(p.bills as TimelineBill[]).map(b => `${b.name} ${fmt(b.amount)}`).join(', ')} → ${fmt(asDollars(p.balance))} left`}
          </title>
        </circle>
      ))}

      {/* payday marker */}
      {geo.points.filter(p => p.isPayday).map(p => (
        <g key="payday">
          <line x1={p.x} x2={p.x} y1="4" y2={CHART_H - 4} stroke={tone} strokeOpacity="0.35" strokeWidth="1" strokeDasharray="2 3" vectorEffect="non-scaling-stroke" />
          <circle cx={p.x} cy={p.y} r="3.5" fill="none" stroke={tone} strokeWidth="2">
            <title>{`Payday ${fmtDate(p.date)} — ${fmt(asDollars(p.balance))} left`}</title>
          </circle>
        </g>
      ))}
    </svg>
  );
}

function UpcomingList({ upcoming }: { upcoming: SafeToSpendUpcoming[] }) {
  const { visible, overflow } = splitUpcoming(upcoming, 4);

  if (visible.length === 0) {
    return (
      <div className="flex h-full flex-col items-start justify-center gap-1.5">
        <span className="inline-flex items-center gap-1.5 text-sm font-medium text-emerald-600 dark:text-emerald-300">
          <Sparkles className="h-4 w-4" /> All bills covered
        </span>
        <p className="text-[11px] text-muted-foreground">Nothing else is due before payday.</p>
      </div>
    );
  }

  return (
    <ul className="space-y-1.5">
      {visible.map(bill => (
        <li key={bill.id} className="flex items-baseline justify-between gap-3 text-sm">
          <span className="min-w-0 truncate text-foreground/90">
            {bill.name}
            <span className={cn(
              'ml-1.5 text-[10px] uppercase tracking-wide',
              bill.status === 'late' || bill.status === 'missed'
                ? 'font-semibold text-rose-500 dark:text-rose-300'
                : 'text-muted-foreground',
            )}>
              {bill.status === 'late' || bill.status === 'missed' ? 'overdue' : shortDate(bill.due_date)}
            </span>
          </span>
          <span className="shrink-0 font-mono text-foreground/80">{fmt(bill.amount)}</span>
        </li>
      ))}
      {overflow > 0 && (
        <li className="text-[11px] text-muted-foreground">+{overflow} more before payday</li>
      )}
    </ul>
  );
}

/**
 * Safe-to-Spend hero card: what's left for the current 1st/15th period after
 * everything still due before the next payday is covered. Sits directly under
 * the summary cards and reads from the tracker payload's `cashflow` block.
 */
export default function CashFlowCard({ cashflow, onSetStartingAmounts }: { cashflow?: TrackerCashflow | null; onSetStartingAmounts?: () => void }) {
  if (!cashflow) return null;

  // No starting amounts and no bank sync — invite setup instead of guessing.
  if (!cashflow.has_data) {
    return (
      <motion.section
        initial={{ opacity: 0, y: 6 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.25 }}
        className="relative overflow-hidden rounded-xl border border-dashed border-border/80 bg-card/60 px-5 py-4"
      >
        <div className="flex flex-wrap items-center justify-between gap-3">
          <div className="flex items-center gap-3">
            <Wallet className="h-5 w-5 text-muted-foreground" />
            <div>
              <p className="text-sm font-semibold text-foreground">See your safe-to-spend</p>
              <p className="text-[11px] text-muted-foreground">
                Add what's in your account for the 1st and 15th, and BillTracker projects what's left after bills.
              </p>
            </div>
          </div>
          <button
            onClick={onSetStartingAmounts}
            className="inline-flex items-center gap-1.5 rounded-lg border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-accent"
          >
            Set starting amounts <ArrowRight className="h-3.5 w-3.5" />
          </button>
        </div>
      </motion.section>
    );
  }

  const safe = Number(cashflow.safe_to_spend ?? 0);
  const positive = safe >= 0;

  return (
    <motion.section
      initial={{ opacity: 0, y: 6 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.25 }}
      className={cn(
        'relative overflow-hidden rounded-xl border border-border/80 bg-card/95 shadow-sm shadow-black/15',
        positive
          ? 'shadow-[0_4px_24px_rgba(16,185,129,0.10)]'
          : 'border-rose-400/35 shadow-[0_4px_24px_rgba(244,63,94,0.12)]',
      )}
      aria-label="Safe to spend"
    >
      <div className={cn(
        'absolute top-0 left-0 right-0 h-[3px] bg-gradient-to-r',
        positive ? 'from-emerald-500 via-teal-400 to-emerald-300' : 'from-rose-500 via-rose-400 to-orange-300',
      )} />

      <div className="grid gap-5 px-5 py-4 md:grid-cols-[200px,minmax(0,1fr),220px] md:items-center">
        {/* ── Number ── */}
        <div>
          <div className="mb-2 flex items-center gap-2">
            <Wallet className={cn('h-4 w-4', positive ? 'text-emerald-500 dark:text-emerald-300' : 'text-rose-500 dark:text-rose-300')} />
            <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Safe to spend</p>
          </div>
          <p
            className={cn(
              'font-mono text-[2rem] font-bold leading-none tracking-tight',
              positive ? 'text-emerald-600 dark:text-emerald-200' : 'text-rose-500 dark:text-rose-300',
            )}
            title={`${fmt(cashflow.available)} available − ${fmt(cashflow.still_due_total)} still due before payday`}
          >
            {positive ? '' : '−'}{fmt(asDollars(Math.abs(safe)))}
          </p>
          <p className="mt-2 inline-flex items-center gap-1 text-[11px] text-muted-foreground">
            <CalendarClock className="h-3.5 w-3.5" />
            until {shortDate(cashflow.next_payday)} · {daysUntilLabel(cashflow.days_until_payday)}
          </p>
        </div>

        {/* ── Projection ── */}
        <div className="min-w-0">
          <TimelineChart timeline={cashflow.timeline} positive={positive} />
          <p className="mt-1 text-center text-[10px] text-muted-foreground/70">
            {fmt(cashflow.available)} on hand → {cashflow.still_due_count === 0
              ? 'no bills left before payday'
              : `${cashflow.still_due_count} bill${cashflow.still_due_count === 1 ? '' : 's'} (${fmt(cashflow.still_due_total)}) before payday`}
          </p>
        </div>

        {/* ── Upcoming ── */}
        <div className="md:border-l md:border-border/60 md:pl-5">
          <p className="mb-2 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
            Due before payday
          </p>
          <UpcomingList upcoming={cashflow.upcoming} />
        </div>
      </div>
    </motion.section>
  );
}
