import { useCallback, useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import {
  Bell,
  CalendarDays,
  CheckCircle2,
  Cloud,
  Loader2,
  Pause,
  Plus,
  RefreshCw,
  Repeat,
  Sparkles,
  X,
} from 'lucide-react';
import { api } from '@/api';
import { cn, fmt, fmtDate } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import BillModal from '@/components/BillModal';

const TYPE_LABELS = {
  streaming: 'Streaming',
  software: 'Software',
  cloud: 'Cloud',
  music: 'Music',
  news: 'News',
  fitness: 'Fitness',
  gaming: 'Gaming',
  utilities: 'Utilities',
  insurance: 'Insurance',
  other: 'Other',
};

function cycleLabel(item) {
  const cycle = item.cycle_type || item.billing_cycle || 'monthly';
  return cycle === 'annual' || cycle === 'annually' ? 'yearly' : cycle;
}

function StatCard({ icon: Icon, label, value, hint }) {
  return (
    <div className="rounded-lg border border-border/70 bg-card/80 p-4">
      <div className="flex items-center gap-2 text-xs font-semibold uppercase tracking-wide text-foreground/70">
        <Icon className="h-4 w-4 text-primary" />
        {label}
      </div>
      <p className="tracker-number mt-2 text-2xl font-bold tracking-tight text-foreground">{value}</p>
      {hint && <p className="mt-1 text-xs font-medium text-muted-foreground">{hint}</p>}
    </div>
  );
}

function SubscriptionRow({ item, onEdit, onToggle }) {
  return (
    <div className={cn(
      'flex flex-col gap-3 border-b border-border/40 px-4 py-4 last:border-b-0 sm:flex-row sm:items-center',
      !item.active && 'opacity-60',
    )}>
      <div className="min-w-0 flex-1">
        <div className="flex flex-wrap items-center gap-2">
          <button
            type="button"
            onClick={() => onEdit(item)}
            className="truncate text-left text-[15px] font-semibold text-foreground hover:text-primary"
          >
            {item.name}
          </button>
          <Badge variant="outline" className="capitalize border-primary/25 bg-primary/10 text-primary">
            {TYPE_LABELS[item.subscription_type] || 'Other'}
          </Badge>
          {!item.active && (
            <Badge variant="outline" className="border-amber-500/25 bg-amber-500/10 text-amber-300">
              Paused
            </Badge>
          )}
        </div>
        <div className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs font-medium text-muted-foreground">
          <span>{item.category_name || 'Uncategorized'}</span>
          <span>Due {fmtDate(item.next_due_date)}</span>
          <span className="capitalize">{cycleLabel(item)}</span>
          <span>{item.reminder_days_before ?? 3}d reminder</span>
        </div>
      </div>

      <div className="grid grid-cols-2 gap-3 sm:w-[260px]">
        <div>
          <p className="text-xs text-muted-foreground">Per cycle</p>
          <p className="tracker-number text-sm font-semibold text-foreground">{fmt(item.expected_amount)}</p>
        </div>
        <div>
          <p className="text-xs text-muted-foreground">Monthly</p>
          <p className="tracker-number text-sm font-semibold text-emerald-600 dark:text-emerald-300">{fmt(item.monthly_equivalent)}</p>
        </div>
      </div>

      <div className="flex gap-2 sm:justify-end">
        <Button type="button" variant="outline" size="sm" onClick={() => onEdit(item)}>
          Edit
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          className={item.active ? 'text-amber-300 hover:bg-amber-500/10 hover:text-amber-200' : 'text-emerald-300 hover:bg-emerald-500/10 hover:text-emerald-200'}
          onClick={() => onToggle(item)}
        >
          {item.active ? 'Pause' : 'Resume'}
        </Button>
      </div>
    </div>
  );
}

function RecommendationCard({ recommendation, categoryId, onAccept, onDecline, busy }) {
  return (
    <div className="rounded-lg border border-primary/20 bg-primary/[0.05] p-4">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
        <div className="min-w-0">
          <div className="flex flex-wrap items-center gap-2">
            <p className="truncate text-sm font-semibold text-foreground">{recommendation.name}</p>
            <Badge variant="outline" className="border-primary/25 bg-primary/10 text-primary">
              {recommendation.confidence}% match
            </Badge>
          </div>
          <p className="mt-1 text-xs font-medium text-muted-foreground">
            {TYPE_LABELS[recommendation.subscription_type] || 'Other'} · {recommendation.occurrence_count} charges · last seen {fmtDate(recommendation.last_seen_date)}
          </p>
          <div className="mt-3 flex flex-wrap gap-2">
            {recommendation.reasons?.map(reason => (
              <span key={reason} className="rounded-md border border-border/60 bg-background/60 px-2 py-1 text-[11px] font-medium text-muted-foreground">
                {reason}
              </span>
            ))}
          </div>
        </div>
        <div className="shrink-0 text-left sm:text-right">
          <p className="tracker-number text-base font-semibold text-foreground">{fmt(recommendation.expected_amount)}</p>
          <p className="tracker-number text-xs font-semibold text-emerald-600 dark:text-emerald-300">
            {fmt(recommendation.monthly_equivalent)} / mo
          </p>
          <div className="mt-3 flex gap-2 sm:justify-end">
            <Button
              type="button"
              size="sm"
              variant="ghost"
              className="gap-1.5 text-muted-foreground hover:text-destructive"
              disabled={busy}
              onClick={() => onDecline(recommendation)}
            >
              {busy ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <X className="h-3.5 w-3.5" />}
              Decline
            </Button>
            <Button
              type="button"
              size="sm"
              className="gap-2"
              disabled={busy}
              onClick={() => onAccept({ ...recommendation, category_id: categoryId })}
            >
              {busy ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <CheckCircle2 className="h-3.5 w-3.5" />}
              Track
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
}

export default function SubscriptionsPage() {
  const [data, setData] = useState({ summary: {}, subscriptions: [] });
  const [recommendations, setRecommendations] = useState([]);
  const [categories, setCategories] = useState([]);
  const [loading, setLoading] = useState(true);
  const [recommendationsLoading, setRecommendationsLoading] = useState(true);
  const [busyId, setBusyId] = useState(null);
  const [modal, setModal] = useState(null);

  const subscriptionCategoryId = useMemo(() => {
    const match = categories.find(category => /subscrip/i.test(category.name));
    return match?.id || null;
  }, [categories]);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const [subscriptionData, categoryData] = await Promise.all([
        api.subscriptions(),
        api.categories(),
      ]);
      setData(subscriptionData);
      setCategories(categoryData || []);
    } catch (err) {
      toast.error(err.message || 'Failed to load subscriptions.');
    } finally {
      setLoading(false);
    }
  }, []);

  const loadRecommendations = useCallback(async () => {
    setRecommendationsLoading(true);
    try {
      const result = await api.subscriptionRecommendations();
      setRecommendations(result.recommendations || []);
    } catch (err) {
      toast.error(err.message || 'Failed to scan subscription recommendations.');
    } finally {
      setRecommendationsLoading(false);
    }
  }, []);

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

  async function refreshAll() {
    await Promise.all([load(), loadRecommendations()]);
  }

  async function toggleSubscription(item) {
    setBusyId(`toggle-${item.id}`);
    try {
      await api.updateSubscription(item.id, { active: !item.active });
      toast.success(item.active ? 'Subscription paused' : 'Subscription resumed');
      await load();
    } catch (err) {
      toast.error(err.message || 'Subscription could not be updated.');
    } finally {
      setBusyId(null);
    }
  }

  async function acceptRecommendation(recommendation) {
    setBusyId(`rec-${recommendation.id}`);
    try {
      await api.createSubscriptionFromRecommendation(recommendation);
      toast.success(`${recommendation.name} is now tracked.`);
      await refreshAll();
    } catch (err) {
      toast.error(err.message || 'Could not create subscription.');
    } finally {
      setBusyId(null);
    }
  }

  async function declineRecommendation(recommendation) {
    if (!recommendation.decline_key) return;
    setBusyId(`dec-${recommendation.id}`);
    try {
      await api.declineRecommendation(recommendation.decline_key);
      setRecommendations(prev => prev.filter(r => r.id !== recommendation.id));
    } catch (err) {
      toast.error(err.message || 'Could not dismiss recommendation.');
    } finally {
      setBusyId(null);
    }
  }

  function openManualSubscription() {
    setModal({
      bill: null,
      initialBill: {
        name: '',
        category_id: subscriptionCategoryId,
        due_day: new Date().getDate(),
        expected_amount: '',
        billing_cycle: 'monthly',
        cycle_type: 'monthly',
        cycle_day: String(new Date().getDate()),
        is_subscription: 1,
        subscription_type: 'other',
        reminder_days_before: 3,
      },
    });
  }

  const summary = data.summary || {};
  const subscriptions = data.subscriptions || [];
  const active = subscriptions.filter(item => item.active);
  const paused = subscriptions.filter(item => !item.active);

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
        <div>
          <p className="mb-1 text-[11px] font-semibold uppercase tracking-[0.15em] text-muted-foreground">
            Recurring Services
          </p>
          <h1 className="text-3xl font-semibold tracking-tight">Subscriptions</h1>
          <p className="mt-1 text-sm text-muted-foreground">
            Track manual subscriptions and review recurring SimpleFIN charges.
          </p>
        </div>
        <div className="flex flex-wrap gap-2">
          <Button type="button" variant="outline" className="gap-2" onClick={refreshAll} disabled={loading || recommendationsLoading}>
            <RefreshCw className={cn('h-4 w-4', (loading || recommendationsLoading) && 'animate-spin')} />
            Refresh
          </Button>
          <Button type="button" className="gap-2" onClick={openManualSubscription}>
            <Plus className="h-4 w-4" />
            Add Subscription
          </Button>
        </div>
      </div>

      <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
        <StatCard icon={Repeat} label="Monthly" value={fmt(summary.monthly_total)} hint={`${summary.active_count || 0} active subscriptions`} />
        <StatCard icon={CalendarDays} label="Yearly" value={fmt(summary.yearly_total)} hint="Normalized yearly impact" />
        <StatCard icon={Pause} label="Paused" value={summary.paused_count || 0} hint="Kept but not active" />
        <StatCard icon={Cloud} label="Top Type" value={summary.top_type ? TYPE_LABELS[summary.top_type.type] || summary.top_type.type : '—'} hint={summary.top_type ? `${fmt(summary.top_type.monthly_total)} / mo` : 'No active subscriptions'} />
      </div>

      <div className="grid gap-5 xl:grid-cols-[minmax(0,1fr)_420px]">
        <Card className="overflow-hidden">
          <CardHeader className="pb-3">
            <CardTitle className="text-base">Tracked Subscriptions</CardTitle>
            <CardDescription>Subscriptions are bills with recurring-service metadata.</CardDescription>
          </CardHeader>
          <CardContent className="p-0">
            {loading ? (
              <div className="p-4">
                {Array.from({ length: 4 }).map((_, index) => (
                  <div key={index} className="mb-2 h-20 animate-pulse rounded-lg bg-muted/40" />
                ))}
              </div>
            ) : subscriptions.length === 0 ? (
              <div className="px-4 py-14 text-center">
                <Repeat className="mx-auto h-8 w-8 text-muted-foreground" />
                <p className="mt-3 text-sm font-medium">No subscriptions tracked yet.</p>
                <p className="mt-1 text-sm text-muted-foreground">Add one manually or accept a SimpleFIN recommendation.</p>
              </div>
            ) : (
              <>
                {active.map(item => (
                  <SubscriptionRow key={item.id} item={item} onEdit={bill => setModal({ bill })} onToggle={toggleSubscription} />
                ))}
                {paused.map(item => (
                  <SubscriptionRow key={item.id} item={item} onEdit={bill => setModal({ bill })} onToggle={toggleSubscription} />
                ))}
              </>
            )}
          </CardContent>
        </Card>

        <Card className="overflow-hidden">
          <CardHeader className="pb-3">
            <div className="flex items-center gap-2">
              <Sparkles className="h-4 w-4 text-primary" />
              <CardTitle className="text-base">SimpleFIN Recommendations</CardTitle>
            </div>
            <CardDescription>Recurring unmatched bank charges that look like subscriptions.</CardDescription>
          </CardHeader>
          <CardContent className="space-y-3">
            {recommendationsLoading ? (
              <div className="rounded-lg border border-border/60 bg-muted/20 px-4 py-10 text-center text-sm text-muted-foreground">
                Scanning transactions...
              </div>
            ) : recommendations.length === 0 ? (
              <div className="rounded-lg border border-dashed border-border/70 px-4 py-10 text-center">
                <Bell className="mx-auto h-7 w-7 text-muted-foreground" />
                <p className="mt-3 text-sm font-medium">No recommendations right now.</p>
                <p className="mt-1 text-sm text-muted-foreground">Sync SimpleFIN after a few recurring charges appear.</p>
              </div>
            ) : (
              recommendations.map(recommendation => (
                <RecommendationCard
                  key={recommendation.id}
                  recommendation={recommendation}
                  categoryId={subscriptionCategoryId}
                  busy={busyId === `rec-${recommendation.id}` || busyId === `dec-${recommendation.id}`}
                  onAccept={acceptRecommendation}
                  onDecline={declineRecommendation}
                />
              ))
            )}
          </CardContent>
        </Card>
      </div>

      {modal && (
        <BillModal
          key={modal.bill?.id ? `subscription-edit-${modal.bill.id}` : 'subscription-new'}
          bill={modal.bill}
          initialBill={modal.initialBill}
          categories={categories}
          onClose={() => setModal(null)}
          onSave={async () => {
            setModal(null);
            await refreshAll();
          }}
        />
      )}
    </div>
  );
}
