import { useCallback, useEffect, useState, type ReactNode } from 'react';
import { Link } from 'react-router-dom';
import { CalendarDays, Copy, Eye, KeyRound, RefreshCw, ShieldOff, Settings2 } from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@/api';
import { cn, errMessage } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';

interface CalFeed {
  active?: boolean;
  feed_url?: string;
  last_used_at?: string | null;
}

interface CalEvent {
  uid: string;
  name?: string;
  due_date?: string;
  cycle_type?: string;
  amount?: number;
}

function PlatformNote({ title, children }: { title: ReactNode; children: ReactNode }) {
  return (
    <div className="rounded-md bg-muted/35 p-3">
      <p className="font-medium text-foreground">{title}</p>
      <p className="mt-1">{children}</p>
    </div>
  );
}

export function CalendarFeedManager({ compact = false, showManageLink = false }: { compact?: boolean; showManageLink?: boolean }) {
  const [feed, setFeed] = useState<CalFeed | null>(null);
  const [preview, setPreview] = useState<CalEvent[]>([]);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState<string | null>(null);

  const loadFeed = useCallback(async () => {
    setLoading(true);
    try {
      const data = await api.calendarFeed() as CalFeed;
      setFeed(data);
      if (data?.active) {
        const nextPreview = await api.calendarFeedPreview(10) as { events?: CalEvent[] };
        setPreview(nextPreview.events || []);
      } else {
        setPreview([]);
      }
    } catch (err) {
      toast.error(errMessage(err, 'Failed to load calendar feed.'));
    } finally {
      setLoading(false);
    }
  }, []);

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

  const active = !!feed?.active && !!feed?.feed_url;

  async function createFeed() {
    setBusy('create');
    try {
      const data = await api.createCalendarFeed() as CalFeed;
      setFeed(data);
      const nextPreview = await api.calendarFeedPreview(10) as { events?: CalEvent[] };
      setPreview(nextPreview.events || []);
      toast.success('Calendar feed created.');
    } catch (err) {
      toast.error(errMessage(err, 'Failed to create calendar feed.'));
    } finally {
      setBusy(null);
    }
  }

  async function copyFeedUrl() {
    if (!feed?.feed_url) return;
    try {
      await navigator.clipboard.writeText(feed.feed_url);
      toast.success('Calendar feed URL copied.');
    } catch {
      toast.error('Copy failed. Select the URL and copy it manually.');
    }
  }

  async function regenerateFeed() {
    setBusy('regenerate');
    try {
      const data = await api.regenerateCalendarFeed() as CalFeed;
      setFeed(data);
      const nextPreview = await api.calendarFeedPreview(10) as { events?: CalEvent[] };
      setPreview(nextPreview.events || []);
      toast.success('Calendar feed regenerated. Update any subscribed calendars with the new URL.');
    } catch (err) {
      toast.error(errMessage(err, 'Failed to regenerate calendar feed.'));
    } finally {
      setBusy(null);
    }
  }

  async function revokeFeed() {
    setBusy('revoke');
    try {
      const data = await api.revokeCalendarFeed() as CalFeed;
      setFeed(data);
      setPreview([]);
      toast.success('Calendar feed revoked.');
    } catch (err) {
      toast.error(errMessage(err, 'Failed to revoke calendar feed.'));
    } finally {
      setBusy(null);
    }
  }

  return (
    <div className={cn('space-y-4', compact ? '' : 'px-4 py-4 sm:px-6')}>
      <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <CalendarDays className="h-4 w-4 text-primary" />
            <p className="text-sm font-medium">Subscribe from Apple Calendar, Google Calendar, Android, Outlook, or any ICS calendar.</p>
          </div>
          <p className="mt-1 max-w-2xl text-xs leading-5 text-muted-foreground">
            This creates a private calendar feed URL. Nothing is added automatically; copy the URL into your calendar app to subscribe.
          </p>
        </div>

        {!loading && !active && (
          <Button size="sm" onClick={createFeed} disabled={!!busy} className="w-full gap-2 sm:w-auto">
            <KeyRound className="h-3.5 w-3.5" />
            {busy === 'create' ? 'Creating...' : 'Create Feed'}
          </Button>
        )}
      </div>

      {loading && (
        <div className="h-24 animate-pulse rounded-lg bg-muted/50" />
      )}

      {!loading && !active && (
        <div className="rounded-lg border border-border/70 bg-muted/20 p-4">
          <p className="text-sm font-medium">What happens next?</p>
          <div className="mt-3 grid gap-2 text-xs text-muted-foreground sm:grid-cols-3">
            <div className="rounded-md bg-background/60 p-3">
              <p className="font-medium text-foreground">1. Create</p>
              <p className="mt-1">Generate a private feed URL for your bill calendar.</p>
            </div>
            <div className="rounded-md bg-background/60 p-3">
              <p className="font-medium text-foreground">2. Copy</p>
              <p className="mt-1">Paste it into Apple, Google, Outlook, or Android calendar setup.</p>
            </div>
            <div className="rounded-md bg-background/60 p-3">
              <p className="font-medium text-foreground">3. Subscribe</p>
              <p className="mt-1">Your calendar app refreshes bill due dates when it checks the feed.</p>
            </div>
          </div>
        </div>
      )}

      {!loading && active && (
        <>
          <div className="rounded-lg border border-amber-500/25 bg-amber-500/[0.08] px-3 py-2 text-xs leading-5 text-amber-800 dark:text-amber-200">
            Anyone with this URL can see the bill events in this feed. Regenerate or revoke it if it was shared somewhere it should not be.
          </div>

          <div className="flex flex-col gap-2 sm:flex-row">
            <Input value={feed?.feed_url ?? ''} readOnly className="min-w-0 flex-1 font-mono text-xs" aria-label="Calendar feed URL" />
            <Button size="sm" variant="outline" onClick={copyFeedUrl} className="gap-2">
              <Copy className="h-3.5 w-3.5" />
              Copy URL
            </Button>
            <Button asChild size="sm" variant="outline" className="gap-2">
              <a href={feed?.feed_url} target="_blank" rel="noreferrer">
                <Eye className="h-3.5 w-3.5" />
                Preview ICS
              </a>
            </Button>
          </div>

          <div className="grid gap-3 text-xs text-muted-foreground lg:grid-cols-4">
            <PlatformNote title="Apple Calendar">
              Add a calendar subscription with the copied URL. The feed uses all-day dates to avoid timezone shifts.
            </PlatformNote>
            <PlatformNote title="Google / Android">
              In Google Calendar on the web, use Other calendars, From URL. Android follows Google Calendar sync.
            </PlatformNote>
            <PlatformNote title="Outlook">
              Subscribe from Outlook on the web with this URL. Imported copies will not update; subscriptions will.
            </PlatformNote>
            <PlatformNote title="Duplicate Safety">
              Bill Tracker emits stable event IDs per bill cycle so subscribed calendars can update without double-adding events.
            </PlatformNote>
          </div>

          <div className="rounded-lg border border-border/70">
            <div className="flex flex-col gap-1 border-b border-border/60 px-3 py-2 sm:flex-row sm:items-center sm:justify-between">
              <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Next events that will appear</p>
              <span className="text-xs text-muted-foreground">
                Last fetched: {feed?.last_used_at ? new Date(feed.last_used_at).toLocaleString() : 'Not yet'}
              </span>
            </div>
            <div className="divide-y divide-border/50">
              {preview.length === 0 && (
                <p className="px-3 py-4 text-sm text-muted-foreground">No upcoming bill events in the preview window.</p>
              )}
              {preview.map(event => (
                <div key={event.uid} className="flex items-center justify-between gap-3 px-3 py-2 text-sm">
                  <div className="min-w-0">
                    <p className="truncate font-medium">{event.name}</p>
                    <p className="text-xs text-muted-foreground">{event.due_date} · {event.cycle_type}</p>
                  </div>
                  <span className="tracker-number shrink-0 text-xs font-semibold">${Number(event.amount || 0).toFixed(2)}</span>
                </div>
              ))}
            </div>
          </div>

          <div className="flex flex-col gap-2 sm:flex-row sm:justify-end">
            {showManageLink && (
              <Button asChild size="sm" variant="ghost" className="gap-2">
                <Link to="/settings#calendar-feed">
                  <Settings2 className="h-3.5 w-3.5" />
                  Manage in Settings
                </Link>
              </Button>
            )}
            <Button size="sm" variant="outline" onClick={regenerateFeed} disabled={!!busy} className="gap-2">
              <RefreshCw className="h-3.5 w-3.5" />
              {busy === 'regenerate' ? 'Regenerating...' : 'Regenerate URL'}
            </Button>
            <Button size="sm" variant="outline" onClick={revokeFeed} disabled={!!busy} className="gap-2 border-destructive/30 text-destructive hover:bg-destructive/10">
              <ShieldOff className="h-3.5 w-3.5" />
              {busy === 'revoke' ? 'Revoking...' : 'Revoke Feed'}
            </Button>
          </div>
        </>
      )}
    </div>
  );
}
