import React from "react";
import { Link, useLocation, useParams } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import {
  Sheet,
  SheetTrigger,
  SheetContent,
  SheetTitle,
  SheetDescription,
  SheetFooter,
} from '@/components/ui/sheet';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import { Settings, ArrowLeft, FileText, RefreshCcw, ChevronRight, UserCircle, LifeBuoy } from 'lucide-react';
import { useOptionalGuestIdentity } from '../context/GuestIdentityContext';
import { LegalMarkdown } from './legal-markdown';
import { useLocale, type LocaleContextValue } from '../i18n/LocaleContext';
import { useTranslation } from '../i18n/useTranslation';
import type { LocaleCode } from '../i18n/messages';
import { useHapticsPreference } from '../hooks/useHapticsPreference';
import { triggerHaptic } from '../lib/haptics';
import { getHelpSlugForPathname } from '../lib/helpRouting';

const legalPages = [
  { slug: 'impressum', translationKey: 'settings.legal.section.impressum' },
  { slug: 'datenschutz', translationKey: 'settings.legal.section.privacy' },
  { slug: 'agb', translationKey: 'settings.legal.section.terms' },
] as const;

type ViewState =
  | { mode: 'home' }
  | {
      mode: 'legal';
      slug: (typeof legalPages)[number]['slug'];
      translationKey: (typeof legalPages)[number]['translationKey'];
    };

type LegalDocumentState =
  | { phase: 'idle'; title: string; markdown: string; html: string }
  | { phase: 'loading'; title: string; markdown: string; html: string }
  | { phase: 'ready'; title: string; markdown: string; html: string }
  | { phase: 'error'; title: string; markdown: string; html: string };

type NameStatus = 'idle' | 'saved';

export function SettingsSheet() {
  const [open, setOpen] = React.useState(false);
  const [view, setView] = React.useState<ViewState>({ mode: 'home' });
  const identity = useOptionalGuestIdentity();
  const localeContext = useLocale();
  const { t } = useTranslation();
  const params = useParams<{ token?: string }>();
  const location = useLocation();
  const [nameDraft, setNameDraft] = React.useState(identity?.name ?? '');
  const [nameStatus, setNameStatus] = React.useState<NameStatus>('idle');
  const [savingName, setSavingName] = React.useState(false);
  const isLegal = view.mode === 'legal';
  const legalDocument = useLegalDocument(isLegal ? view.slug : null, localeContext.locale);
  const helpSlug = getHelpSlugForPathname(location.pathname);
  const helpBase = params?.token ? `/e/${encodeURIComponent(params.token)}/help` : '/help';
  const helpHref = helpSlug ? `${helpBase}/${helpSlug}` : helpBase;

  React.useEffect(() => {
    if (open && identity?.hydrated) {
      setNameDraft(identity.name ?? '');
      setNameStatus('idle');
    }
  }, [open, identity?.hydrated, identity?.name]);

  const handleBack = React.useCallback(() => {
    setView({ mode: 'home' });
  }, []);

  const handleOpenLegal = React.useCallback(
    (
      slug: (typeof legalPages)[number]['slug'],
      translationKey: (typeof legalPages)[number]['translationKey'],
    ) => {
      setView({ mode: 'legal', slug, translationKey });
    },
    [],
  );

  const handleOpenChange = React.useCallback((next: boolean) => {
    setOpen(next);
    if (!next) {
      setView({ mode: 'home' });
      setNameStatus('idle');
    }
  }, []);

  const canSaveName = Boolean(
    identity?.hydrated && nameDraft.trim() && nameDraft.trim() !== (identity?.name ?? '')
  );

  const handleSaveName = React.useCallback(() => {
    if (!identity || !canSaveName) {
      return;
    }
    setSavingName(true);
    try {
      identity.setName(nameDraft);
      setNameStatus('saved');
      window.setTimeout(() => setNameStatus('idle'), 2000);
    } finally {
      setSavingName(false);
    }
  }, [identity, nameDraft, canSaveName]);

  const handleResetName = React.useCallback(() => {
    if (!identity) return;
    identity.clearName();
    setNameDraft('');
    setNameStatus('idle');
  }, [identity]);

  return (
    <Sheet open={open} onOpenChange={handleOpenChange}>
      <SheetTrigger asChild>
        <Button variant="ghost" size="icon" className="h-9 w-9 rounded-md">
          <Settings className="h-5 w-5" />
          <span className="sr-only">{t('settings.sheet.openLabel')}</span>
        </Button>
      </SheetTrigger>
      <SheetContent side="right" className="sm:max-w-md">
        <div className="flex h-full flex-col">
          <header className="border-b bg-background px-6 py-4">
            {isLegal ? (
              <div className="flex items-center gap-3">
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-9 w-9"
                  onClick={handleBack}
                >
                  <ArrowLeft className="h-5 w-5" />
                  <span className="sr-only">{t('settings.sheet.backLabel')}</span>
                </Button>
                <div className="min-w-0">
                  <SheetTitle className="truncate">
                    {legalDocument.phase === 'ready' && legalDocument.title
                      ? legalDocument.title
                      : t(view.translationKey)}
                  </SheetTitle>
                  <SheetDescription>
                    {legalDocument.phase === 'loading'
                      ? t('common.actions.loading')
                      : t('settings.sheet.legalDescription')}
                  </SheetDescription>
                </div>
              </div>
            ) : (
              <div>
                <SheetTitle>{t('settings.title')}</SheetTitle>
                <SheetDescription>{t('settings.subtitle')}</SheetDescription>
              </div>
            )}
          </header>

          <main className="flex-1 overflow-y-auto px-6 py-4">
            {isLegal ? (
              <LegalView
                document={legalDocument}
                onClose={() => handleOpenChange(false)}
                translationKey={view.mode === 'legal' ? view.translationKey : null}
              />
            ) : (
              <HomeView
                identity={identity}
                nameDraft={nameDraft}
                onNameChange={setNameDraft}
                onSaveName={handleSaveName}
                onResetName={handleResetName}
                canSaveName={canSaveName}
                savingName={savingName}
                nameStatus={nameStatus}
                localeContext={localeContext}
                onOpenLegal={handleOpenLegal}
                helpHref={helpHref}
              />
            )}
          </main>

          <SheetFooter className="border-t bg-muted/40 px-6 py-3 text-xs text-muted-foreground">
            <div>{t('settings.footer.notice')}</div>
          </SheetFooter>
        </div>
      </SheetContent>
    </Sheet>
  );
}

function LegalView({
  document,
  onClose,
  translationKey,
}: {
  document: LegalDocumentState;
  onClose: () => void;
  translationKey: string | null;
}) {
  const { t } = useTranslation();

  if (document.phase === 'error') {
    return (
      <div className="space-y-4">
        <Alert variant="destructive">
          <AlertDescription>
            {t('settings.legal.error')}
          </AlertDescription>
        </Alert>
        <Button variant="secondary" onClick={onClose}>
          {t('common.actions.close')}
        </Button>
      </div>
    );
  }

  if (document.phase === 'loading' || document.phase === 'idle') {
    return <div className="text-sm text-muted-foreground">{t('settings.legal.loading')}</div>;
  }

  return (
    <div className="space-y-4">
      <Card>
        <CardHeader>
          <CardTitle>{document.title || t(translationKey ?? 'settings.legal.fallbackTitle')}</CardTitle>
        </CardHeader>
        <CardContent className="prose prose-sm max-w-none dark:prose-invert [&_:where(p,ul,ol,li)]:text-foreground [&_:where(h1,h2,h3,h4,h5,h6)]:text-foreground">
            <LegalMarkdown markdown={document.markdown} html={document.html} />
          </CardContent>
        </Card>
    </div>
  );
}

interface HomeViewProps {
  identity: ReturnType<typeof useOptionalGuestIdentity>;
  nameDraft: string;
  onNameChange: (value: string) => void;
  onSaveName: () => void;
  onResetName: () => void;
  canSaveName: boolean;
  savingName: boolean;
  nameStatus: NameStatus;
  localeContext: LocaleContextValue;
  onOpenLegal: (
    slug: (typeof legalPages)[number]['slug'],
    translationKey: (typeof legalPages)[number]['translationKey'],
  ) => void;
  helpHref: string;
}

function HomeView({
  identity,
  nameDraft,
  onNameChange,
  onSaveName,
  onResetName,
  canSaveName,
  savingName,
  nameStatus,
  localeContext,
  onOpenLegal,
  helpHref,
}: HomeViewProps) {
  const { t } = useTranslation();
  const { enabled: hapticsEnabled, setEnabled: setHapticsEnabled, supported: hapticsSupported } = useHapticsPreference();
  const legalLinks = React.useMemo(
    () =>
      legalPages.map((page) => ({
        slug: page.slug,
        translationKey: page.translationKey,
        label: t(page.translationKey),
      })),
    [t],
  );

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader className="pb-3">
          <CardTitle>{t('settings.language.title')}</CardTitle>
          <CardDescription>{t('settings.language.description')}</CardDescription>
        </CardHeader>
        <CardContent>
          <div className="grid grid-cols-2 gap-2">
            {localeContext.availableLocales.map((option) => {
              const isActive = localeContext.locale === option.code;
              return (
                <Button
                  key={option.code}
                  type="button"
                  variant={isActive ? 'default' : 'outline'}
                  className={`flex h-12 flex-col justify-center gap-1 rounded-lg border text-sm ${
                    isActive ? 'bg-pink-500 text-white hover:bg-pink-600' : 'bg-background'
                  }`}
                  onClick={() => localeContext.setLocale(option.code)}
                  aria-pressed={isActive}
                  disabled={!localeContext.hydrated}
                >
                  <span aria-hidden className="text-lg leading-none">{option.flag}</span>
                  <span className="font-medium">{t(`settings.language.option.${option.code}`)}</span>
                  {isActive && (
                    <Badge
                      variant="secondary"
                      className="border border-white/40 bg-white/10 text-[10px] uppercase tracking-wide text-white"
                    >
                      {t('settings.language.activeBadge')}
                    </Badge>
                  )}
                </Button>
              );
            })}
          </div>
        </CardContent>
      </Card>

      {identity && (
        <Card>
          <CardHeader className="pb-3">
            <CardTitle>{t('settings.name.title')}</CardTitle>
            <CardDescription>{t('settings.name.description')}</CardDescription>
          </CardHeader>
          <CardContent className="space-y-3">
            <div className="flex items-center gap-3">
              <div className="flex h-12 w-12 items-center justify-center rounded-full bg-pink-100 text-pink-600">
                <UserCircle className="h-6 w-6" />
              </div>
              <div className="flex-1 space-y-2">
                <Label htmlFor="guest-name" className="text-sm font-medium">
                  {t('settings.name.label')}
                </Label>
                <Input
                  id="guest-name"
                  value={nameDraft}
                  placeholder={t('settings.name.placeholder')}
                  onChange={(event) => onNameChange(event.target.value)}
                  autoComplete="name"
                  disabled={!identity.hydrated || savingName}
                />
              </div>
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <Button onClick={onSaveName} disabled={!canSaveName || savingName}>
                {savingName ? t('settings.name.saving') : t('settings.name.save')}
              </Button>
              <Button type="button" variant="ghost" onClick={onResetName} disabled={savingName}>
                {t('settings.name.reset')}
              </Button>
              {nameStatus === 'saved' && (
                <span className="text-xs text-muted-foreground">{t('settings.name.saved')}</span>
              )}
              {!identity.hydrated && (
                <span className="text-xs text-muted-foreground">{t('settings.name.loading')}</span>
              )}
            </div>
          </CardContent>
        </Card>
      )}

      <Card>
        <CardHeader className="pb-3">
          <CardTitle>{t('settings.haptics.title')}</CardTitle>
          <CardDescription>{t('settings.haptics.description')}</CardDescription>
        </CardHeader>
        <CardContent className="space-y-2">
          <div className="flex items-center justify-between gap-4">
            <span className="text-sm font-medium">{t('settings.haptics.label')}</span>
            <Switch
              checked={hapticsEnabled}
              onCheckedChange={(checked) => {
                setHapticsEnabled(checked);
                if (checked) {
                  triggerHaptic('selection');
                }
              }}
              disabled={!hapticsSupported}
              aria-label={t('settings.haptics.label')}
            />
          </div>
          {!hapticsSupported && (
            <div className="text-xs text-muted-foreground">{t('settings.haptics.unsupported')}</div>
          )}
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="pb-3">
          <CardTitle>
            <div className="flex items-center gap-2">
              <FileText className="h-4 w-4 text-pink-500" />
              {t('settings.legal.title')}
            </div>
          </CardTitle>
          <CardDescription>{t('settings.legal.description')}</CardDescription>
        </CardHeader>
        <CardContent className="space-y-2">
          {legalLinks.map((page) => (
            <Button
              key={page.slug}
              variant="ghost"
              className="w-full justify-between px-3"
              onClick={() => onOpenLegal(page.slug, page.translationKey)}
            >
              <span className="text-left text-sm">{page.label}</span>
              <ChevronRight className="h-4 w-4" />
            </Button>
          ))}
        </CardContent>
      </Card>

      <Card>
        <CardHeader className="pb-3">
          <CardTitle>
            <div className="flex items-center gap-2">
              <LifeBuoy className="h-4 w-4 text-pink-500" />
              {t('settings.help.title')}
            </div>
          </CardTitle>
          <CardDescription>{t('settings.help.description')}</CardDescription>
        </CardHeader>
        <CardContent>
          <Button asChild className="w-full">
            <Link to={helpHref}>{t('settings.help.cta')}</Link>
          </Button>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>{t('settings.cache.title')}</CardTitle>
          <CardDescription>{t('settings.cache.description')}</CardDescription>
        </CardHeader>
        <CardContent className="space-y-3">
          <ClearCacheButton />
          <div className="flex items-start gap-2 text-xs text-muted-foreground">
            <RefreshCcw className="mt-0.5 h-3.5 w-3.5" />
            <span>{t('settings.cache.note')}</span>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}

function useLegalDocument(slug: string | null, locale: LocaleCode): LegalDocumentState {
  const [state, setState] = React.useState<LegalDocumentState>({
    phase: 'idle',
    title: '',
    markdown: '',
    html: '',
  });

  React.useEffect(() => {
    if (!slug) {
      setState({ phase: 'idle', title: '', markdown: '', html: '' });
      return;
    }

    const controller = new AbortController();
    setState({ phase: 'loading', title: '', markdown: '', html: '' });

    const langParam = encodeURIComponent(locale);
    fetch(`/api/v1/legal/${encodeURIComponent(slug)}?lang=${langParam}`, {
      headers: { 'Cache-Control': 'no-store' },
      signal: controller.signal,
    })
      .then(async (res) => {
        if (!res.ok) {
          throw new Error('failed');
        }
        const payload = await res.json();
        setState({
          phase: 'ready',
          title: payload.title ?? '',
          markdown: payload.body_markdown ?? '',
          html: payload.body_html ?? '',
        });
      })
      .catch((error) => {
        if (controller.signal.aborted) {
          return;
        }
        console.error('Failed to load legal page', error);
        setState({ phase: 'error', title: '', markdown: '', html: '' });
      });

    return () => controller.abort();
  }, [slug, locale]);

  return state;
}

function ClearCacheButton() {
  const [busy, setBusy] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const { t } = useTranslation();

  async function clearAll() {
    setBusy(true);
    setDone(false);
    try {
      if ('caches' in window) {
        const keys = await caches.keys();
        await Promise.all(keys.map((key) => caches.delete(key)));
      }
      if ('indexedDB' in window) {
        try {
          await new Promise((resolve) => {
            const request = indexedDB.deleteDatabase('upload-queue');
            request.onsuccess = () => resolve(null);
            request.onerror = () => resolve(null);
          });
        } catch (error) {
          console.warn('IndexedDB cleanup failed', error);
        }
      }
      setDone(true);
    } finally {
      setBusy(false);
      window.setTimeout(() => setDone(false), 2500);
    }
  }

  return (
    <div className="space-y-2">
      <Button variant="secondary" onClick={clearAll} disabled={busy} className="w-full">
        {busy ? t('settings.cache.clearing') : t('settings.cache.clear')}
      </Button>
      {done && <div className="text-xs text-muted-foreground">{t('settings.cache.cleared')}</div>}
    </div>
  );
}
