import React from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { ArrowLeft, Copy, Loader2, QrCode, RefreshCw, Share2, Sparkles, X } from 'lucide-react';

import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';

import { AdminLayout } from '../components/AdminLayout';
import {
  createQrInvite,
  EventQrInvite,
  getEvent,
  getEventQrInvites,
  revokeEventQrInvite,
  TenantEvent,
  updateEventQrInvite,
  EventQrInviteLayout,
} from '../api';
import { isAuthError } from '../auth/tokens';
import {
  ADMIN_EVENTS_PATH,
  ADMIN_EVENT_VIEW_PATH,
  ADMIN_EVENT_TOOLKIT_PATH,
  ADMIN_EVENT_PHOTOS_PATH,
} from '../constants';
import { InviteLayoutCustomizerPanel, QrLayoutCustomization } from './components/InviteLayoutCustomizerPanel';

interface PageState {
  event: TenantEvent | null;
  invites: EventQrInvite[];
  loading: boolean;
  error: string | null;
}

export default function EventInvitesPage(): JSX.Element {
  const { slug } = useParams<{ slug?: string }>();
  const navigate = useNavigate();
  const { t } = useTranslation('management');

  const [state, setState] = React.useState<PageState>({ event: null, invites: [], loading: true, error: null });
  const [creatingInvite, setCreatingInvite] = React.useState(false);
  const [revokingId, setRevokingId] = React.useState<number | null>(null);
  const [selectedInviteId, setSelectedInviteId] = React.useState<number | null>(null);
  const [copiedInviteId, setCopiedInviteId] = React.useState<number | null>(null);
  const [customizerSaving, setCustomizerSaving] = React.useState(false);
  const [customizerResetting, setCustomizerResetting] = React.useState(false);

  const load = React.useCallback(async () => {
    if (!slug) {
      setState({ event: null, invites: [], loading: false, error: 'Kein Event-Slug angegeben.' });
      return;
    }

    setState((prev) => ({ ...prev, loading: true, error: null }));
    try {
      const [eventData, invitesData] = await Promise.all([getEvent(slug), getEventQrInvites(slug)]);
      setState({ event: eventData, invites: invitesData, loading: false, error: null });
      setSelectedInviteId((current) => current ?? invitesData[0]?.id ?? null);
    } catch (error) {
      if (!isAuthError(error)) {
        setState({ event: null, invites: [], loading: false, error: 'QR-Einladungen konnten nicht geladen werden.' });
      }
    }
  }, [slug]);

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

  const event = state.event;
  const eventName = event ? renderEventName(event.name) : t('toolkit.titleFallback', 'Event');

  const selectedInvite = React.useMemo(
    () => state.invites.find((invite) => invite.id === selectedInviteId) ?? null,
    [state.invites, selectedInviteId]
  );

  React.useEffect(() => {
    if (state.invites.length === 0) {
      setSelectedInviteId(null);
      return;
    }
    setSelectedInviteId((current) => {
      if (current && state.invites.some((invite) => invite.id === current)) {
        return current;
      }
      return state.invites[0]?.id ?? null;
    });
  }, [state.invites]);

  const currentCustomization = React.useMemo(() => {
    if (!selectedInvite) {
      return null;
    }
    const metadata = selectedInvite.metadata as Record<string, unknown> | undefined | null;
    const raw = metadata?.layout_customization;
    return raw && typeof raw === 'object' ? (raw as QrLayoutCustomization) : null;
  }, [selectedInvite]);

  React.useEffect(() => {
    if (selectedInvite) {
      console.debug('[Invites] Selected invite', selectedInvite.id, selectedInvite.layouts, selectedInvite.layouts_url);
    }
  }, [selectedInvite]);

  const inviteCountSummary = React.useMemo(() => {
    const active = state.invites.filter((invite) => invite.is_active && !invite.revoked_at).length;
    const total = state.invites.length;
    return { active, total };
  }, [state.invites]);

  async function handleCreateInvite() {
    if (!slug || creatingInvite) {
      return;
    }

    setCreatingInvite(true);
    setState((prev) => ({ ...prev, error: null }));
    try {
      const invite = await createQrInvite(slug);
      setState((prev) => ({
        ...prev,
        invites: [invite, ...prev.invites.filter((existing) => existing.id !== invite.id)],
      }));
      setSelectedInviteId(invite.id);
      try {
        await navigator.clipboard.writeText(invite.url);
        setCopiedInviteId(invite.id);
      } catch {
        // ignore clipboard failures
      }
    } catch (error) {
      if (!isAuthError(error)) {
        setState((prev) => ({ ...prev, error: 'QR-Einladung konnte nicht erstellt werden.' }));
      }
    } finally {
      setCreatingInvite(false);
    }
  }

  async function handleCopy(invite: EventQrInvite) {
    try {
      await navigator.clipboard.writeText(invite.url);
      setCopiedInviteId(invite.id);
    } catch (error) {
      console.warn('[Invites] Clipboard copy failed', error);
    }
  }

  React.useEffect(() => {
    if (!copiedInviteId) return;
    const timeout = setTimeout(() => setCopiedInviteId(null), 3000);
    return () => clearTimeout(timeout);
  }, [copiedInviteId]);

  async function handleRevoke(invite: EventQrInvite) {
    if (!slug || invite.revoked_at) {
      return;
    }

    setRevokingId(invite.id);
    setState((prev) => ({ ...prev, error: null }));
    try {
      const updated = await revokeEventQrInvite(slug, invite.id);
      setState((prev) => ({
        ...prev,
        invites: prev.invites.map((existing) => (existing.id === updated.id ? updated : existing)),
      }));
      if (selectedInviteId === invite.id && !updated.is_active) {
        setSelectedInviteId((prevId) => (prevId === updated.id ? null : prevId));
      }
    } catch (error) {
      if (!isAuthError(error)) {
        setState((prev) => ({ ...prev, error: 'QR-Einladung konnte nicht deaktiviert werden.' }));
      }
    } finally {
      setRevokingId(null);
    }
  }

  async function handleSaveCustomization(customization: QrLayoutCustomization) {
    if (!slug || !selectedInvite) {
      return;
    }

    setCustomizerSaving(true);
    setState((prev) => ({ ...prev, error: null }));
    try {
      const updated = await updateEventQrInvite(slug, selectedInvite.id, {
        metadata: { layout_customization: customization },
      });
      setState((prev) => ({
        ...prev,
        invites: prev.invites.map((invite) => (invite.id === updated.id ? updated : invite)),
      }));
    } catch (error) {
      if (!isAuthError(error)) {
        setState((prev) => ({ ...prev, error: 'Anpassung konnte nicht gespeichert werden.' }));
      }
    } finally {
      setCustomizerSaving(false);
    }
  }

  async function handleResetCustomization() {
    if (!slug || !selectedInvite) {
      return;
    }

    setCustomizerResetting(true);
    setState((prev) => ({ ...prev, error: null }));
    try {
      const updated = await updateEventQrInvite(slug, selectedInvite.id, {
        metadata: { layout_customization: null },
      });
      setState((prev) => ({
        ...prev,
        invites: prev.invites.map((invite) => (invite.id === updated.id ? updated : invite)),
      }));
    } catch (error) {
      if (!isAuthError(error)) {
        setState((prev) => ({ ...prev, error: 'Anpassungen konnten nicht zurückgesetzt werden.' }));
      }
    } finally {
      setCustomizerResetting(false);
    }
  }

  const actions = (
    <>
      <Button variant="outline" onClick={() => navigate(ADMIN_EVENTS_PATH)} className="border-pink-200 text-pink-600 hover:bg-pink-50">
        <ArrowLeft className="h-4 w-4" />
        {t('invites.actions.backToList', 'Zurück zur Übersicht')}
      </Button>
      {slug ? (
        <>
          <Button variant="outline" onClick={() => navigate(ADMIN_EVENT_VIEW_PATH(slug))} className="border-slate-200 text-slate-600 hover:bg-slate-50">
            {t('invites.actions.backToEvent', 'Event öffnen')}
          </Button>
          <Button variant="outline" onClick={() => navigate(ADMIN_EVENT_PHOTOS_PATH(slug))} className="border-sky-200 text-sky-700 hover:bg-sky-50">
            {t('toolkit.actions.moderate', 'Fotos moderieren')}
          </Button>
          <Button variant="outline" onClick={() => navigate(ADMIN_EVENT_TOOLKIT_PATH(slug))} className="border-emerald-200 text-emerald-600 hover:bg-emerald-50">
            {t('toolkit.actions.backToEvent', 'Event-Day Toolkit')}
          </Button>
        </>
      ) : null}
    </>
  );

  return (
    <AdminLayout
      title={eventName}
      subtitle={t('invites.subtitle', 'Manage QR-Einladungen, Drucklayouts und Branding für deine Gäste.')}
      actions={actions}
    >
      {state.error ? (
        <Alert variant="destructive">
          <AlertTitle>{t('invites.errorTitle', 'Aktion fehlgeschlagen')}</AlertTitle>
          <AlertDescription>{state.error}</AlertDescription>
        </Alert>
      ) : null}

      <Card className="border-0 bg-white/90 shadow-xl shadow-amber-100/60">
        <CardHeader className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
          <div className="space-y-2">
            <CardTitle className="flex items-center gap-2 text-xl text-slate-900">
              <QrCode className="h-5 w-5 text-amber-500" />
              {t('invites.cardTitle', 'QR-Einladungen & Layouts')}
            </CardTitle>
            <CardDescription className="text-sm text-slate-600">
              {t('invites.cardDescription', 'Erzeuge Einladungen, passe Layouts an und stelle druckfertige Vorlagen bereit.')}
            </CardDescription>
            <div className="rounded-lg border border-amber-100 bg-amber-50/70 px-3 py-2 text-xs text-amber-700">
              {t('invites.summary.active', 'Aktive Einladungen')}: {inviteCountSummary.active} ·{' '}
              {t('invites.summary.total', 'Gesamt')}: {inviteCountSummary.total}
            </div>
          </div>
          <div className="flex flex-wrap items-center gap-2">
            <Button variant="outline" onClick={() => void load()} disabled={state.loading} className="border-amber-200 text-amber-700 hover:bg-amber-100">
              {state.loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <RefreshCw className="h-4 w-4" />}
              {t('invites.actions.refresh', 'Aktualisieren')}
            </Button>
            <Button
              onClick={handleCreateInvite}
              disabled={creatingInvite}
              className="bg-gradient-to-r from-amber-500 via-orange-500 to-rose-500 text-white shadow-lg shadow-amber-500/20"
            >
              {creatingInvite ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Share2 className="mr-2 h-4 w-4" />}
              {t('invites.actions.create', 'Neue Einladung erstellen')}
            </Button>
          </div>
        </CardHeader>
        <CardContent className="space-y-4">
          {state.loading ? (
            <InviteSkeleton />
          ) : state.invites.length === 0 ? (
            <EmptyState onCreate={handleCreateInvite} />
          ) : (
            <div className="grid gap-3">
              {state.invites.map((invite) => (
                <InviteListCard
                  key={invite.id}
                  invite={invite}
                  onSelect={() => setSelectedInviteId(invite.id)}
                  onCopy={() => handleCopy(invite)}
                  onRevoke={() => handleRevoke(invite)}
                  selected={invite.id === selectedInvite?.id}
                  revoking={revokingId === invite.id}
                  copied={copiedInviteId === invite.id}
                />
              ))}
            </div>
          )}
        </CardContent>
      </Card>

      <InviteLayoutCustomizerPanel
        invite={selectedInvite ?? null}
        eventName={eventName}
        saving={customizerSaving}
        resetting={customizerResetting}
        onSave={handleSaveCustomization}
        onReset={handleResetCustomization}
        initialCustomization={currentCustomization}
      />
    </AdminLayout>
  );
}

function InviteListCard({
  invite,
  selected,
  onSelect,
  onCopy,
  onRevoke,
  revoking,
  copied,
}: {
  invite: EventQrInvite;
  selected: boolean;
  onSelect: () => void;
  onCopy: () => void;
  onRevoke: () => void;
  revoking: boolean;
  copied: boolean;
}) {
  const { t } = useTranslation('management');
  const status = getInviteStatus(invite);
  const metadata = (invite.metadata ?? {}) as Record<string, unknown>;
  const customization = (metadata.layout_customization ?? null) as QrLayoutCustomization | null;
  const preferredLayoutId = customization?.layout_id ?? invite.layouts[0]?.id ?? null;
  const isAutoGenerated = Boolean(metadata.auto_generated);
  const usageLabel = invite.usage_limit ? `${invite.usage_count} / ${invite.usage_limit}` : `${invite.usage_count}`;

  const layoutsById = React.useMemo(() => {
    const map = new Map<string, EventQrInviteLayout>();
    invite.layouts.forEach((layout) => map.set(layout.id, layout));
    return map;
  }, [invite.layouts]);

  const layoutName = preferredLayoutId ? layoutsById.get(preferredLayoutId)?.name ?? invite.layouts[0]?.name ?? '' : '';

  return (
    <div
      role="button"
      tabIndex={0}
      onClick={onSelect}
      onKeyDown={(event) => {
        if (event.key === 'Enter' || event.key === ' ') {
          event.preventDefault();
          onSelect();
        }
      }}
      className={`flex flex-col gap-3 rounded-2xl border p-4 transition-shadow ${selected ? 'border-amber-400 bg-amber-50/70 shadow-lg shadow-amber-200/30' : 'border-slate-200 bg-white/80 hover:border-amber-200'}`}
    >
      <div className="flex flex-wrap items-center gap-2">
        <span className="text-sm font-semibold text-slate-900">{invite.label?.trim() || `Einladung #${invite.id}`}</span>
        <Badge variant="outline" className={statusBadgeClass(status)}>
          {status}
        </Badge>
        {isAutoGenerated ? (
          <Badge variant="secondary" className="bg-slate-200 text-slate-700">{t('invites.labels.standard', 'Standard')}</Badge>
        ) : null}
        {customization ? (
          <Badge className="bg-emerald-500/15 text-emerald-700">{t('tasks.customizer.badge', 'Angepasst')}</Badge>
        ) : null}
      </div>

      <div className="flex flex-wrap items-center gap-2">
        <span className="break-all rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 font-mono text-xs text-slate-700">
          {invite.url}
        </span>
        <Button
          variant="outline"
          size="sm"
          onClick={(event) => {
            event.stopPropagation();
            onCopy();
          }}
          className={copied ? 'border-emerald-300 text-emerald-700 hover:bg-emerald-50' : 'border-amber-200 text-amber-700 hover:bg-amber-100'}
        >
          <Copy className="mr-1 h-3 w-3" />
          {copied ? t('invites.actions.copied', 'Kopiert!') : t('invites.actions.copy', 'Link kopieren')}
        </Button>
      </div>

      <div className="grid gap-1 text-xs text-slate-500 sm:grid-cols-2">
        <span>
          {t('invites.labels.usage', 'Nutzung')}: {usageLabel}
        </span>
        <span>
          {t('invites.labels.layout', 'Layout')}: {layoutName || t('invites.labels.layoutFallback', 'Standard')}
        </span>
        {invite.expires_at ? <span>{t('invites.labels.validUntil', 'Gültig bis')} {formatDateTime(invite.expires_at)}</span> : null}
        {invite.created_at ? <span>{t('invites.labels.createdAt', 'Erstellt am')} {formatDateTime(invite.created_at)}</span> : null}
      </div>

      <div className="flex flex-wrap items-center justify-between gap-2">
        {selected ? (
          <Badge variant="outline" className="border-amber-300 bg-amber-100/70 text-amber-700">
            {t('invites.labels.selected', 'Aktuell ausgewählt')}
          </Badge>
        ) : (
          <div className="text-xs text-slate-500">{t('invites.labels.tapToEdit', 'Zum Anpassen auswählen')}</div>
        )}
        <Button
          variant="ghost"
          size="sm"
          onClick={(event) => {
            event.stopPropagation();
            onRevoke();
          }}
          disabled={revoking || invite.revoked_at !== null || !invite.is_active}
          className="text-slate-500 hover:text-rose-500 disabled:opacity-50"
        >
          {revoking ? <Loader2 className="mr-1 h-4 w-4 animate-spin" /> : <X className="mr-1 h-4 w-4" />}
          {t('invites.actions.deactivate', 'Deaktivieren')}
        </Button>
      </div>
    </div>
  );
}

function InviteSkeleton() {
  return (
    <div className="space-y-3">
      {Array.from({ length: 3 }).map((_, index) => (
        <div key={`invite-skeleton-${index}`} className="h-32 animate-pulse rounded-2xl bg-gradient-to-r from-white/40 via-white/60 to-white/40" />
      ))}
    </div>
  );
}

function EmptyState({ onCreate }: { onCreate: () => void }) {
  const { t } = useTranslation('management');
  return (
    <div className="flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed border-slate-200 bg-slate-50/60 p-10 text-center">
      <h3 className="text-base font-semibold text-slate-800">{t('invites.empty.title', 'Noch keine Einladungen')}</h3>
      <p className="text-sm text-slate-500">{t('invites.empty.copy', 'Erstelle eine Einladung, um druckfertige QR-Layouts zu erhalten.')}</p>
      <Button onClick={onCreate} className="bg-gradient-to-r from-amber-500 via-orange-500 to-rose-500 text-white">
        <Share2 className="mr-1 h-4 w-4" />
        {t('invites.actions.create', 'Neue Einladung erstellen')}
      </Button>
    </div>
  );
}

function renderEventName(name: TenantEvent['name']): string {
  if (typeof name === 'string') {
    return name;
  }
  if (name && typeof name === 'object') {
    return name.de ?? name.en ?? Object.values(name)[0] ?? 'Event';
  }
  return 'Event';
}

function getInviteStatus(invite: EventQrInvite): 'Aktiv' | 'Deaktiviert' | 'Abgelaufen' {
  if (invite.revoked_at) return 'Deaktiviert';
  if (invite.expires_at) {
    const expiry = new Date(invite.expires_at);
    if (!Number.isNaN(expiry.getTime()) && expiry.getTime() < Date.now()) {
      return 'Abgelaufen';
    }
  }
  return invite.is_active ? 'Aktiv' : 'Deaktiviert';
}

function statusBadgeClass(status: string): string {
  if (status === 'Aktiv') {
    return 'bg-emerald-100 text-emerald-700 border-emerald-200';
  }
  if (status === 'Abgelaufen') {
    return 'bg-orange-100 text-orange-700 border-orange-200';
  }
  return 'bg-slate-200 text-slate-700 border-slate-300';
}

function formatDateTime(iso: string | null): string {
  if (!iso) return 'unbekannt';
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) {
    return 'unbekannt';
  }
  return date.toLocaleString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}
