import React from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Image as ImageIcon, RefreshCcw, UploadCloud, Trash2, ChevronDown, Save } from 'lucide-react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite';
import { MobileShell } from './components/MobileShell';
import { MobileCard, CTAButton } from './components/Primitives';
import { TenantEvent, getEvent, updateEvent, getTenantFonts, TenantFont } from '../api';
import { isAuthError } from '../auth/tokens';
import { ApiError, getApiErrorMessage } from '../lib/apiError';
import { MobileSheet } from './components/Sheet';
import toast from 'react-hot-toast';

type BrandingForm = {
  primary: string;
  accent: string;
  headingFont: string;
  bodyFont: string;
  logoDataUrl: string;
};

export default function MobileBrandingPage() {
  const { slug: slugParam } = useParams<{ slug?: string }>();
  const slug = slugParam ?? null;
  const navigate = useNavigate();
  const { t } = useTranslation('management');

  const [event, setEvent] = React.useState<TenantEvent | null>(null);
  const [form, setForm] = React.useState<BrandingForm>({
    primary: '#007AFF',
    accent: '#5AD2F4',
    headingFont: '',
    bodyFont: '',
    logoDataUrl: '',
  });
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const [showFontsSheet, setShowFontsSheet] = React.useState(false);
  const [fontField, setFontField] = React.useState<'heading' | 'body'>('heading');
  const [fonts, setFonts] = React.useState<TenantFont[]>([]);
  const [fontsLoading, setFontsLoading] = React.useState(false);
  const [fontsLoaded, setFontsLoaded] = React.useState(false);

  React.useEffect(() => {
    if (!slug) return;
    (async () => {
      setLoading(true);
      try {
        const data = await getEvent(slug);
        setEvent(data);
        setForm(extractBranding(data));
        setError(null);
      } catch (err) {
        if (!isAuthError(err)) {
          setError(getApiErrorMessage(err, t('events.errors.loadFailed', 'Branding konnte nicht geladen werden.')));
        }
      } finally {
        setLoading(false);
      }
    })();
  }, [slug, t]);

  React.useEffect(() => {
    if (!showFontsSheet || fontsLoaded) return;
    setFontsLoading(true);
    getTenantFonts()
      .then((data) => setFonts(data ?? []))
      .catch(() => undefined)
      .finally(() => {
        setFontsLoading(false);
        setFontsLoaded(true);
      });
  }, [showFontsSheet, fontsLoaded]);

  const previewTitle = event ? renderName(event.name) : t('events.placeholders.untitled', 'Unbenanntes Event');
  const previewHeadingFont = form.headingFont || 'Montserrat';
  const previewBodyFont = form.bodyFont || 'Montserrat';

  async function handleSave() {
    if (!event?.slug) return;
    const eventTypeId = event.event_type_id ?? event.event_type?.id ?? null;
    if (!eventTypeId) {
      const msg = t('events.errors.missingType', 'Event type fehlt. Speichere das Event erneut im Admin.');
      setError(msg);
      toast.error(msg);
      return;
    }
    setSaving(true);
    setError(null);
    try {
      const payload = {
        name: typeof event.name === 'string' ? event.name : renderName(event.name),
        slug: event.slug,
        event_type_id: eventTypeId,
        event_date: event.event_date ?? undefined,
        status: event.status ?? 'draft',
        is_active: event.is_active ?? undefined,
      };
      const settings = { ...(event.settings ?? {}) };
      settings.branding = {
        ...(typeof settings.branding === 'object' ? (settings.branding as Record<string, unknown>) : {}),
        primary_color: form.primary,
        accent_color: form.accent,
        heading_font: form.headingFont,
        body_font: form.bodyFont,
        typography: {
          ...(typeof (settings.branding as Record<string, unknown> | undefined)?.typography === 'object'
            ? ((settings.branding as Record<string, unknown>).typography as Record<string, unknown>)
            : {}),
          heading: form.headingFont,
          body: form.bodyFont,
        },
        palette: {
          ...(typeof (settings.branding as Record<string, unknown> | undefined)?.palette === 'object'
            ? ((settings.branding as Record<string, unknown>).palette as Record<string, unknown>)
            : {}),
          primary: form.primary,
          secondary: form.accent,
        },
        logo_data_url: form.logoDataUrl || null,
        logo: form.logoDataUrl
          ? {
              mode: 'upload',
              value: form.logoDataUrl,
              position: 'center',
              size: 'm',
            }
          : null,
      };
      const updated = await updateEvent(event.slug, {
        ...payload,
        settings,
      });
      setEvent(updated);
      toast.success(t('events.branding.saveSuccess', 'Branding gespeichert'));
    } catch (err) {
      if (!isAuthError(err)) {
        let message = getApiErrorMessage(err, t('events.errors.saveFailed', 'Branding konnte nicht gespeichert werden.'));
        if (err instanceof ApiError && err.meta?.errors && typeof err.meta.errors === 'object') {
          const allErrors = Object.values(err.meta.errors as Record<string, unknown>)
            .flat()
            .filter((val): val is string => typeof val === 'string');
          if (allErrors.length) {
            message = allErrors.join('\n');
          }
        }
        setError(message);
        toast.error(message, { duration: 5000 });
      }
    } finally {
      setSaving(false);
    }
  }

  function handleReset() {
    if (event) {
      setForm(extractBranding(event));
    }
  }

  return (
    <MobileShell
      activeTab="home"
      title={t('events.branding.titleShort', 'Branding')}
      onBack={() => navigate(-1)}
      headerActions={
        <Pressable disabled={saving} onPress={() => handleSave()}>
          <Save size={18} color="#007AFF" />
        </Pressable>
      }
    >
      {error ? (
        <MobileCard>
          <Text fontWeight="700" color="#b91c1c">
            {error}
          </Text>
        </MobileCard>
      ) : null}

      <MobileCard space="$3">
        <Text fontSize="$sm" fontWeight="700" color="#111827">
          {t('events.branding.previewTitle', 'Guest App Preview')}
        </Text>
        <YStack borderRadius={16} borderWidth={1} borderColor="#e5e7eb" backgroundColor="#f8fafc" padding="$3" space="$2" alignItems="center">
          <YStack width="100%" borderRadius={12} backgroundColor="white" borderWidth={1} borderColor="#e5e7eb" overflow="hidden">
            <YStack backgroundColor={form.primary} height={64} />
            <YStack padding="$3" space="$1.5">
              <Text fontSize="$md" fontWeight="800" color="#111827" style={{ fontFamily: previewHeadingFont }}>
                {previewTitle}
              </Text>
              <Text fontSize="$sm" color="#4b5563" style={{ fontFamily: previewBodyFont }}>
                {t('events.branding.previewSubtitle', 'Aktuelle Farben & Schriften')}
              </Text>
              <XStack space="$2" marginTop="$1">
                <ColorSwatch color={form.primary} label={t('events.branding.primary', 'Primary')} />
                <ColorSwatch color={form.accent} label={t('events.branding.accent', 'Accent')} />
              </XStack>
            </YStack>
          </YStack>
        </YStack>
      </MobileCard>

      <MobileCard space="$3">
        <Text fontSize="$md" fontWeight="800" color="#111827">
          {t('events.branding.colors', 'Colors')}
        </Text>
        <ColorField
          label={t('events.branding.primary', 'Primary Color')}
          value={form.primary}
          onChange={(value) => setForm((prev) => ({ ...prev, primary: value }))}
        />
        <ColorField
          label={t('events.branding.accent', 'Accent Color')}
          value={form.accent}
          onChange={(value) => setForm((prev) => ({ ...prev, accent: value }))}
        />
      </MobileCard>

      <MobileCard space="$3">
        <Text fontSize="$md" fontWeight="800" color="#111827">
          {t('events.branding.fonts', 'Fonts')}
        </Text>
        <InputField
          label={t('events.branding.headingFont', 'Headline Font')}
          value={form.headingFont}
          placeholder="SF Pro Display"
          onChange={(value) => setForm((prev) => ({ ...prev, headingFont: value }))}
          onPicker={() => {
            setFontField('heading');
            setShowFontsSheet(true);
          }}
        />
        <InputField
          label={t('events.branding.bodyFont', 'Body Font')}
          value={form.bodyFont}
          placeholder="SF Pro Text"
          onChange={(value) => setForm((prev) => ({ ...prev, bodyFont: value }))}
          onPicker={() => {
            setFontField('body');
            setShowFontsSheet(true);
          }}
        />
      </MobileCard>

      <MobileCard space="$3">
        <Text fontSize="$md" fontWeight="800" color="#111827">
          {t('events.branding.logo', 'Logo')}
        </Text>
        <YStack
          borderRadius={14}
          borderWidth={1}
          borderColor="#e5e7eb"
          backgroundColor="#f8fafc"
          padding="$3"
          alignItems="center"
          justifyContent="center"
          space="$2"
        >
          {form.logoDataUrl ? (
            <>
              <img src={form.logoDataUrl} alt="Logo" style={{ maxHeight: 80, maxWidth: '100%', objectFit: 'contain' }} />
              <XStack space="$2">
                <CTAButton
                  label={t('events.branding.replaceLogo', 'Replace logo')}
                  onPress={() => document.getElementById('branding-logo-input')?.click()}
                />
                <Pressable onPress={() => setForm((prev) => ({ ...prev, logoDataUrl: '' }))}>
                  <XStack
                    alignItems="center"
                    space="$1.5"
                    paddingHorizontal="$3"
                    paddingVertical="$2"
                    borderRadius={12}
                    borderWidth={1}
                    borderColor="#e5e7eb"
                  >
                    <Trash2 size={16} color="#b91c1c" />
                    <Text fontSize="$sm" color="#b91c1c" fontWeight="700">
                      {t('events.branding.removeLogo', 'Remove')}
                    </Text>
                  </XStack>
                </Pressable>
              </XStack>
            </>
          ) : (
            <>
              <ImageIcon size={28} color="#94a3b8" />
              <Text fontSize="$sm" color="#4b5563" textAlign="center">
                {t('events.branding.logoHint', 'Upload a logo to brand guest invites and QR posters.')}
              </Text>
              <Pressable onPress={() => document.getElementById('branding-logo-input')?.click()}>
                <XStack
                  alignItems="center"
                  space="$2"
                  paddingHorizontal="$3.5"
                  paddingVertical="$2.5"
                  borderRadius={12}
                  borderWidth={1}
                  borderColor="#e5e7eb"
                  backgroundColor="white"
                >
                  <UploadCloud size={18} color="#007AFF" />
                  <Text fontSize="$sm" color="#007AFF" fontWeight="700">
                    {t('events.branding.uploadLogo', 'Upload logo (max. 1 MB)')}
                  </Text>
                </XStack>
              </Pressable>
            </>
          )}
          <input
            id="branding-logo-input"
            type="file"
            accept="image/*"
            style={{ display: 'none' }}
            onChange={(event) => {
              const file = event.target.files?.[0];
              if (!file) return;
              if (file.size > 1024 * 1024) {
                setError(t('events.branding.logoTooLarge', 'Logo must be under 1 MB.'));
                return;
              }
              const reader = new FileReader();
              reader.onload = () => {
                const nextLogo =
                  typeof reader.result === 'string'
                    ? reader.result
                    : typeof reader.result === 'object' && reader.result !== null
                      ? String(reader.result)
                      : '';
                setForm((prev) => ({ ...prev, logoDataUrl: nextLogo }));
                setError(null);
              };
              reader.readAsDataURL(file);
            }}
          />
        </YStack>
      </MobileCard>

      <YStack space="$2">
        <CTAButton label={saving ? t('events.branding.saving', 'Saving...') : t('events.branding.save', 'Save Branding')} onPress={() => handleSave()} />
        <Pressable disabled={loading || saving} onPress={handleReset}>
          <XStack
            height={52}
            borderRadius={14}
            alignItems="center"
            justifyContent="center"
            backgroundColor="white"
            borderWidth={1}
            borderColor="#e5e7eb"
            space="$2"
          >
            <RefreshCcw size={16} color="#111827" />
            <Text fontSize="$sm" color="#111827" fontWeight="700">
              {t('events.branding.reset', 'Reset to Defaults')}
            </Text>
          </XStack>
        </Pressable>
      </YStack>

      <MobileSheet
        open={showFontsSheet}
        onClose={() => setShowFontsSheet(false)}
        title={t('events.branding.fontPicker', 'Select font')}
        footer={null}
        bottomOffsetPx={120}
      >
        <YStack space="$2">
          {fontsLoading ? (
            Array.from({ length: 4 }).map((_, idx) => <MobileCard key={`font-sk-${idx}`} height={48} opacity={0.6} />)
          ) : fonts.length === 0 ? (
            <Text fontSize="$sm" color="#4b5563">
              {t('events.branding.noFonts', 'Keine Schriftarten gefunden.')}
            </Text>
          ) : (
            fonts.map((font) => (
              <Pressable
                key={font.family}
                onPress={() => {
                  setForm((prev) => ({
                    ...prev,
                    [fontField === 'heading' ? 'headingFont' : 'bodyFont']: font.family,
                  }));
                  setShowFontsSheet(false);
                }}
              >
                <XStack alignItems="center" justifyContent="space-between" paddingVertical="$2">
                  <YStack>
                    <Text fontSize="$sm" color="#111827" style={{ fontFamily: font.family }}>
                      {font.family}
                    </Text>
                    {font.variants?.length ? (
                      <Text fontSize="$xs" color="#6b7280" style={{ fontFamily: font.family }}>
                        {font.variants.map((v) => v.style ?? v.weight ?? '').filter(Boolean).join(', ')}
                      </Text>
                    ) : null}
                  </YStack>
                  {form[fontField === 'heading' ? 'headingFont' : 'bodyFont'] === font.family ? (
                    <Text fontSize="$xs" color="#007AFF">
                      {t('common.active', 'Active')}
                    </Text>
                  ) : null}
                </XStack>
              </Pressable>
            ))
          )}
        </YStack>
      </MobileSheet>
    </MobileShell>
  );
}

function extractBranding(event: TenantEvent): BrandingForm {
  const source = (event.settings as Record<string, unknown>) ?? {};
  const branding = (source.branding as Record<string, unknown>) ?? source;
  const readColor = (key: string, fallback: string) => {
    const value = branding[key];
    return typeof value === 'string' && value.startsWith('#') ? value : fallback;
  };
  const readText = (key: string) => {
    const value = branding[key];
    return typeof value === 'string' ? value : '';
  };
  return {
    primary: readColor('primary_color', '#007AFF'),
    accent: readColor('accent_color', '#5AD2F4'),
    headingFont: readText('heading_font'),
    bodyFont: readText('body_font'),
    logoDataUrl: readText('logo_data_url'),
  };
}

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

function ColorField({ label, value, onChange }: { label: string; value: string; onChange: (next: string) => void }) {
  return (
    <YStack space="$2">
      <Text fontSize="$sm" fontWeight="700" color="#111827">
        {label}
      </Text>
        <XStack alignItems="center" space="$2">
          <input
            type="color"
            value={value}
            onChange={(event) => onChange(event.target.value)}
            style={{ width: 52, height: 52, borderRadius: 12, border: '1px solid #e5e7eb', background: 'white' }}
          />
          <Text fontSize="$sm" color="#4b5563">
            {value}
          </Text>
        </XStack>
    </YStack>
  );
}

function ColorSwatch({ color, label }: { color: string; label: string }) {
  return (
    <YStack alignItems="center" space="$1">
      <YStack width={40} height={40} borderRadius={12} borderWidth={1} borderColor="#e5e7eb" backgroundColor={color} />
      <Text fontSize="$xs" color="#4b5563">
        {label}
      </Text>
    </YStack>
  );
}

function InputField({
  label,
  value,
  placeholder,
  onChange,
  onPicker,
}: {
  label: string;
  value: string;
  placeholder?: string;
  onChange: (next: string) => void;
  onPicker?: () => void;
}) {
  return (
    <YStack space="$2">
      <Text fontSize="$sm" fontWeight="700" color="#111827">
        {label}
      </Text>
      <XStack
        alignItems="center"
        borderRadius={12}
        borderWidth={1}
        borderColor="#e5e7eb"
        paddingLeft="$3"
        paddingRight="$2"
        height={48}
        backgroundColor="white"
        space="$2"
      >
        <input
          type="text"
          value={value}
          placeholder={placeholder}
          onChange={(event) => onChange(event.target.value)}
          style={{
            flex: 1,
            height: '100%',
            border: 'none',
            outline: 'none',
            fontSize: 14,
            background: 'transparent',
          }}
          onFocus={onPicker}
        />
        {onPicker ? (
          <Pressable onPress={onPicker}>
            <ChevronDown size={16} color="#007AFF" />
          </Pressable>
        ) : null}
      </XStack>
    </YStack>
  );
}
