import React from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { CalendarDays, ChevronDown, MapPin, Save, Check } from 'lucide-react';
import { isPast, isSameDay, parseISO, startOfDay } from 'date-fns';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Switch } from '@tamagui/switch';
import { MobileShell } from './components/MobileShell';
import { MobileCard, CTAButton, FloatingActionButton } from './components/Primitives';
import { MobileDateTimeInput, MobileField, MobileInput, MobileSelect, MobileTextArea } from './components/FormControls';
import { LegalConsentSheet } from './components/LegalConsentSheet';
import {
  createEvent,
  getEvent,
  updateEvent,
  getEventTypes,
  getPackages,
  getTenantPackagesOverview,
  Package,
  TenantEvent,
  TenantEventType,
  TenantPackageSummary,
  trackOnboarding,
} from '../api';
import { resolveEventSlugAfterUpdate } from './eventFormNavigation';
import { adminPath } from '../constants';
import { isAuthError } from '../auth/tokens';
import { getApiErrorMessage, getApiValidationMessage, isApiError } from '../lib/apiError';
import toast from 'react-hot-toast';
import { useBackNavigation } from './hooks/useBackNavigation';
import { useAdminTheme } from './theme';
import { withAlpha } from './components/colors';
import { useAuth } from '../auth/context';
import { useEventContext } from '../context/EventContext';

type FormState = {
  name: string;
  date: string;
  eventTypeId: number | null;
  description: string;
  location: string;
  published: boolean;
  autoApproveUploads: boolean;
  tasksEnabled: boolean;
  packageId: number | null;
  servicePackageSlug: string | null;
};

export default function MobileEventFormPage() {
  const { slug: slugParam } = useParams<{ slug?: string }>();
  const slug = slugParam ?? null;
  const isEdit = Boolean(slug);
  const navigate = useNavigate();
  const { t } = useTranslation(['management', 'common']);
  const { user } = useAuth();
  const { selectEvent, refetch } = useEventContext();
  const queryClient = useQueryClient();
  const { text, muted, subtle, danger, border, surface, primary } = useAdminTheme();
  const isSuperAdmin = user?.role === 'super_admin' || user?.role === 'superadmin';

  const [form, setForm] = React.useState<FormState>({
    name: '',
    date: '',
    eventTypeId: null,
    description: '',
    location: '',
    published: false,
    autoApproveUploads: true,
    tasksEnabled: true,
    packageId: null,
    servicePackageSlug: null,
  });
  const [eventMeta, setEventMeta] = React.useState<{ status: TenantEvent['status']; eventDate: string | null } | null>(
    null,
  );
  const [eventTypes, setEventTypes] = React.useState<TenantEventType[]>([]);
  const [typesLoading, setTypesLoading] = React.useState(false);
  const [packages, setPackages] = React.useState<Package[]>([]);
  const [packagesLoading, setPackagesLoading] = React.useState(false);
  const [kontingentOptions, setKontingentOptions] = React.useState<Array<{ slug: string; remaining: number }>>([]);
  const [kontingentLoading, setKontingentLoading] = React.useState(false);
  const [loading, setLoading] = React.useState(isEdit);
  const [saving, setSaving] = React.useState(false);
  const [consentOpen, setConsentOpen] = React.useState(false);
  const [consentBusy, setConsentBusy] = React.useState(false);
  const [pendingPayload, setPendingPayload] = React.useState<Parameters<typeof createEvent>[0] | null>(null);
  const [error, setError] = React.useState<string | null>(null);
  const back = useBackNavigation(slug ? adminPath(`/mobile/events/${slug}`) : adminPath('/mobile/events'));

  React.useEffect(() => {
    if (!slug) {
      setEventMeta(null);
      return;
    }
    (async () => {
      setLoading(true);
      try {
        const data = await getEvent(slug);
        setEventMeta({ status: data.status, eventDate: data.event_date });
        setForm({
          name: renderName(data.name),
          date: toDateTimeLocal(data.event_date),
          eventTypeId: data.event_type_id ?? data.event_type?.id ?? null,
          description: typeof data.description === 'string' ? data.description : '',
          location: resolveLocation(data),
          published: data.status === 'published',
          autoApproveUploads:
            (data.settings?.guest_upload_visibility as string | undefined) === 'immediate',
          tasksEnabled:
            (data.settings?.engagement_mode as string | undefined) !== 'photo_only' &&
            (data.engagement_mode as string | undefined) !== 'photo_only',
          packageId: null,
          servicePackageSlug: null,
        });
        setError(null);
      } catch (err) {
        if (!isAuthError(err)) {
          setError(getApiErrorMessage(err, t('events.errors.loadFailed', 'Event konnte nicht geladen werden.')));
        }
      } finally {
        setLoading(false);
      }
    })();
  }, [slug, t, isEdit]);

  const isEventCompleted = React.useMemo(() => {
    if (!eventMeta) return false;
    if (eventMeta.status === 'archived') return true;
    if (!eventMeta.eventDate) return false;
    const eventDate = parseISO(eventMeta.eventDate);
    const today = startOfDay(new Date());
    if (isSameDay(today, eventDate)) return false;
    return isPast(eventDate);
  }, [eventMeta]);

  const handleDateChange = React.useCallback(
    (event: React.ChangeEvent<HTMLInputElement>) => {
      if (isEventCompleted) return;
      setForm((prev) => ({ ...prev, date: event.target.value }));
    },
    [isEventCompleted],
  );

  React.useEffect(() => {
    (async () => {
      setTypesLoading(true);
      try {
        const types = await getEventTypes();
        setEventTypes(types);
        const preferredType = types.find((type) => type.slug === 'wedding') ?? types[0] ?? null;
        if (preferredType) {
          setForm((prev) => (prev.eventTypeId ? prev : { ...prev, eventTypeId: preferredType.id }));
        }
      } catch {
        // silently ignore; fallback to null
      } finally {
        setTypesLoading(false);
      }
    })();
  }, []);

  React.useEffect(() => {
    if (!isSuperAdmin || isEdit) {
      return;
    }

    (async () => {
      setPackagesLoading(true);
      try {
        const data = await getPackages('endcustomer');
        setPackages(data);
        setForm((prev) => {
          if (prev.packageId) {
            return prev;
          }
          const preferred = data.find((pkg) => pkg.id === 3) ?? data[0] ?? null;
          return { ...prev, packageId: preferred?.id ?? null };
        });
      } catch {
        setPackages([]);
      } finally {
        setPackagesLoading(false);
      }
    })();
  }, [isSuperAdmin, isEdit]);

  React.useEffect(() => {
    if (isEdit) {
      return;
    }

    (async () => {
      setKontingentLoading(true);
      try {
        const overview = await getTenantPackagesOverview();
        const packages = overview.packages ?? [];

        const active = packages.filter((pkg) => pkg.active && pkg.package_type === 'reseller');
        const totals = new Map<string, number>();

        active.forEach((pkg: TenantPackageSummary) => {
          const slugValue = pkg.included_package_slug ?? 'standard';
          if (!slugValue) {
            return;
          }

          const remaining = Number.isFinite(pkg.remaining_events as number) ? Number(pkg.remaining_events) : 0;
          if (remaining <= 0) {
            return;
          }

          totals.set(slugValue, (totals.get(slugValue) ?? 0) + remaining);
        });

        const options = Array.from(totals.entries())
          .map(([slugValue, remaining]) => ({ slug: slugValue, remaining }))
          .sort((a, b) => a.slug.localeCompare(b.slug));

        setKontingentOptions(options);
        setForm((prev) => {
          if (prev.servicePackageSlug || options.length === 0) {
            return prev;
          }

          if (options.length === 1) {
            return { ...prev, servicePackageSlug: options[0].slug };
          }

          const standard = options.find((row) => row.slug === 'standard');
          return { ...prev, servicePackageSlug: standard?.slug ?? options[0].slug };
        });
      } catch {
        setKontingentOptions([]);
      } finally {
        setKontingentLoading(false);
      }
    })();
  }, [isEdit]);

  const resolveServiceTierLabel = React.useCallback((slugValue: string) => {
    if (slugValue === 'starter') {
      return 'Starter';
    }

    if (slugValue === 'standard') {
      return 'Standard';
    }

    if (slugValue === 'pro') {
      return 'Premium';
    }

    return slugValue;
  }, []);

  async function handleSubmit() {
    setSaving(true);
    setError(null);
    try {
      if (isEdit && slug) {
        const updated = await updateEvent(slug, {
          name: form.name,
          event_date: form.date || undefined,
          event_type_id: form.eventTypeId ?? undefined,
          status: form.published ? 'published' : 'draft',
          settings: {
            location: form.location,
            guest_upload_visibility: form.autoApproveUploads ? 'immediate' : 'review',
            engagement_mode: form.tasksEnabled ? 'tasks' : 'photo_only',
          },
        });
        const nextSlug = resolveEventSlugAfterUpdate(slug, updated);
        await queryClient.invalidateQueries({ queryKey: ['tenant-events'] });
        void refetch();
        navigate(adminPath(`/mobile/events/${nextSlug}`));
      } else {
        const payload = {
          name: form.name || t('eventForm.fields.name.fallback', 'Event'),
          slug: `${Date.now()}`,
          event_type_id: form.eventTypeId ?? undefined,
          event_date: form.date || undefined,
          status: form.published ? 'published' : 'draft',
          package_id: isSuperAdmin ? form.packageId ?? undefined : undefined,
          service_package_slug: form.servicePackageSlug ?? undefined,
          settings: {
            location: form.location,
            guest_upload_visibility: form.autoApproveUploads ? 'immediate' : 'review',
            engagement_mode: form.tasksEnabled ? 'tasks' : 'photo_only',
          },
        } as Parameters<typeof createEvent>[0];
        const { event } = await createEvent(payload);
        if (typeof window !== 'undefined' && form.tasksEnabled) {
          try {
            window.sessionStorage.setItem(`tasksDecisionPrompt:${event.id}`, 'pending');
          } catch {
            // ignore storage exceptions
          }
        }
        selectEvent(event.slug);
        void queryClient.invalidateQueries({ queryKey: ['tenant-events'] });
        void refetch();
        void trackOnboarding('event_created', { event_id: event.id });
        navigate(adminPath(`/mobile/events/${event.slug}`));
      }
    } catch (err) {
      if (isAuthError(err)) {
        return;
      }

      if (!isEdit && isWaiverRequiredError(err)) {
        const payload = {
          name: form.name || t('eventForm.fields.name.fallback', 'Event'),
          slug: `${Date.now()}`,
          event_type_id: form.eventTypeId ?? undefined,
          event_date: form.date || undefined,
          status: form.published ? 'published' : 'draft',
          package_id: isSuperAdmin ? form.packageId ?? undefined : undefined,
          service_package_slug: form.servicePackageSlug ?? undefined,
          settings: {
            location: form.location,
            guest_upload_visibility: form.autoApproveUploads ? 'immediate' : 'review',
            engagement_mode: form.tasksEnabled ? 'tasks' : 'photo_only',
          },
        } as Parameters<typeof createEvent>[0];
        setPendingPayload(payload);
        setConsentOpen(true);
        return;
      }

      const message = getApiValidationMessage(err, t('eventForm.errors.saveFailed', 'Event could not be saved.'));
      setError(message);
      toast.error(message);
    } finally {
      setSaving(false);
    }
  }

  async function handleConsentConfirm(consents: { acceptedTerms: boolean; acceptedWaiver: boolean }) {
    if (!pendingPayload) {
      setConsentOpen(false);
      return;
    }

    setConsentBusy(true);
    try {
      const { event } = await createEvent({
        ...pendingPayload,
        accepted_waiver: consents.acceptedWaiver,
      });
      if (typeof window !== 'undefined' && form.tasksEnabled) {
        try {
          window.sessionStorage.setItem(`tasksDecisionPrompt:${event.id}`, 'pending');
        } catch {
          // ignore storage exceptions
        }
      }
      selectEvent(event.slug);
      void queryClient.invalidateQueries({ queryKey: ['tenant-events'] });
      void refetch();
      void trackOnboarding('event_created', { event_id: event.id });
      navigate(adminPath(`/mobile/events/${event.slug}`));
      setConsentOpen(false);
      setPendingPayload(null);
    } catch (err) {
      if (!isAuthError(err)) {
        const message = getApiValidationMessage(err, t('eventForm.errors.saveFailed', 'Event could not be saved.'));
        setError(message);
        toast.error(message);
      }
    } finally {
      setConsentBusy(false);
    }
  }

  return (
    <MobileShell
      activeTab="home"
      title={isEdit ? t('eventForm.titles.edit', 'Edit event') : t('eventForm.titles.create', 'Create event')}
      onBack={back}
    >
      {error ? (
        <MobileCard>
          <Text fontWeight="700" color={danger}>
            {error}
          </Text>
        </MobileCard>
      ) : null}

      <MobileCard space="$3">
        <MobileField label={t('eventForm.fields.name.label', 'Event name')}>
          <MobileInput
            type="text"
            value={form.name}
            onChange={(e) => setForm((prev) => ({ ...prev, name: e.target.value }))}
            placeholder={t('eventForm.fields.name.placeholder', 'e.g. Summer Party 2025')}
          />
        </MobileField>

        {isSuperAdmin && !isEdit ? (
          <MobileField label={t('eventForm.fields.package.label', 'Package')}>
            {packagesLoading ? (
              <Text fontSize="$sm" color={muted}>{t('eventForm.fields.package.loading', 'Loading packages…')}</Text>
            ) : packages.length === 0 ? (
              <Text fontSize="$sm" color={muted}>{t('eventForm.fields.package.empty', 'No packages available yet.')}</Text>
            ) : (
              <MobileSelect
                value={form.packageId ?? ''}
                onChange={(e) => setForm((prev) => ({ ...prev, packageId: Number(e.target.value) }))}
              >
                <option value="">{t('eventForm.fields.package.placeholder', 'Select package')}</option>
                {packages.map((pkg) => (
                  <option key={pkg.id} value={pkg.id}>
                    {pkg.name || `#${pkg.id}`}
                  </option>
                ))}
              </MobileSelect>
            )}
            <Text fontSize="$xs" color={muted}>
              {t('eventForm.fields.package.help', 'This controls the event’s premium limits.')}
            </Text>
          </MobileField>
        ) : null}

        {!isEdit && (kontingentLoading || kontingentOptions.length > 0) ? (
          <MobileField label={t('eventForm.fields.servicePackage.label', 'Event-Level (Event-Kontingent)')}>
            {kontingentLoading ? (
              <Text fontSize="$sm" color={muted}>
                {t('eventForm.fields.servicePackage.loading', 'Loading Event-Kontingente…')}
              </Text>
            ) : (
              <MobileSelect
                value={form.servicePackageSlug ?? ''}
                onChange={(e) => setForm((prev) => ({ ...prev, servicePackageSlug: String(e.target.value) }))}
              >
                <option value="">{t('eventForm.fields.servicePackage.placeholder', 'Select tier')}</option>
                {kontingentOptions.map((opt) => (
                  <option key={opt.slug} value={opt.slug}>
                    {resolveServiceTierLabel(opt.slug)} · {opt.remaining} {t('eventForm.fields.servicePackage.events', 'Events')}
                  </option>
                ))}
              </MobileSelect>
            )}
            <Text fontSize="$xs" color={muted}>
              {t(
                'eventForm.fields.servicePackage.help',
                'Wählt das Event-Level. Pro Event wird 1 aus dem passenden Event-Kontingent verbraucht.',
              )}
            </Text>
          </MobileField>
        ) : null}

        <MobileField label={t('eventForm.fields.date.label', 'Date & time')}>
          <XStack alignItems="center" space="$2">
            <MobileDateTimeInput
              value={form.date}
              onChange={handleDateChange}
              style={{ flex: 1 }}
              disabled={isEventCompleted}
            />
            <CalendarDays size={16} color={subtle} />
          </XStack>
        </MobileField>

        <MobileField label={t('eventForm.fields.type.label', 'Event type')}>
          {typesLoading ? (
            <Text fontSize="$sm" color={muted}>{t('eventForm.fields.type.loading', 'Loading event types…')}</Text>
          ) : eventTypes.length === 0 ? (
            <Text fontSize="$sm" color={muted}>{t('eventForm.fields.type.empty', 'No event types available yet. Please add one in the admin area.')}</Text>
          ) : (
            <MobileSelect
              value={form.eventTypeId ?? ''}
              onChange={(e) => setForm((prev) => ({ ...prev, eventTypeId: Number(e.target.value) }))}
            >
              <option value="">{t('eventForm.fields.type.placeholder', 'Select event type')}</option>
              {eventTypes.map((type) => (
                <option key={type.id} value={type.id}>
                  {renderName(type.name as any) || type.slug}
                </option>
              ))}
            </MobileSelect>
          )}
        </MobileField>

        <MobileField label={t('eventForm.fields.description.label', 'Optional details')}>
          <MobileTextArea
            value={form.description}
            onChange={(e) => setForm((prev) => ({ ...prev, description: e.target.value }))}
            placeholder={t('eventForm.fields.description.placeholder', 'Description')}
          />
        </MobileField>

        <MobileField label={t('eventForm.fields.location.label', 'Location')}>
          <XStack alignItems="center" space="$2">
            <MobileInput
              type="text"
              value={form.location}
              onChange={(e) => setForm((prev) => ({ ...prev, location: e.target.value }))}
              placeholder={t('eventForm.fields.location.placeholder', 'Location')}
              style={{ flex: 1 }}
            />
            <MapPin size={16} color={subtle} />
          </XStack>
        </MobileField>

        <MobileField label={t('eventForm.fields.publish.label', 'Publish immediately')}>
          <XStack alignItems="center" space="$2">
            <Switch
              checked={form.published}
              onCheckedChange={(checked) =>
                setForm((prev) => ({ ...prev, published: Boolean(checked) }))
              }
              size="$3"
              aria-label={t('eventForm.fields.publish.label', 'Publish immediately')}
            >
              <Switch.Thumb />
            </Switch>
            <Text fontSize="$sm" color={text}>
              {form.published ? t('common:states.enabled', 'Enabled') : t('common:states.disabled', 'Disabled')}
            </Text>
          </XStack>
          <Text fontSize="$xs" color={muted}>{t('eventForm.fields.publish.help', 'Enable if guests should see the event right away. You can change the status later.')}</Text>
        </MobileField>

        <MobileField label={t('eventForm.fields.tasksMode.label', 'Tasks & challenges')}>
          <XStack alignItems="center" space="$2">
            <Switch
              checked={form.tasksEnabled}
              onCheckedChange={(checked) =>
                setForm((prev) => ({ ...prev, tasksEnabled: Boolean(checked) }))
              }
              size="$3"
              aria-label={t('eventForm.fields.tasksMode.label', 'Tasks & challenges')}
            >
              <Switch.Thumb />
            </Switch>
            <Text fontSize="$sm" color={text}>
              {form.tasksEnabled
                ? t('common:states.enabled', 'Enabled')
                : t('common:states.disabled', 'Disabled')}
            </Text>
          </XStack>
          <Text fontSize="$xs" color={muted}>
            {form.tasksEnabled
              ? t(
                  'eventForm.fields.tasksMode.helpOn',
                  'Guests can see tasks, challenges and achievements.',
                )
              : t(
                  'eventForm.fields.tasksMode.helpOff',
                  'Task mode is off: guests only see the photo feed.',
                )}
          </Text>
        </MobileField>

        <MobileField label={t('eventForm.fields.uploadVisibility.label', 'Uploads visible immediately')}>
          <XStack alignItems="center" space="$2">
            <Switch
              checked={form.autoApproveUploads}
              onCheckedChange={(checked) =>
                setForm((prev) => ({ ...prev, autoApproveUploads: Boolean(checked) }))
              }
              size="$3"
              aria-label={t('eventForm.fields.uploadVisibility.label', 'Uploads visible immediately')}
            >
              <Switch.Thumb />
            </Switch>
            <Text fontSize="$sm" color={text}>
              {form.autoApproveUploads
                ? t('common:states.enabled', 'Enabled')
                : t('common:states.disabled', 'Disabled')}
            </Text>
          </XStack>
          <Text fontSize="$xs" color={muted}>
            {form.autoApproveUploads
              ? t(
                  'eventForm.fields.uploadVisibility.helpOn',
                  'Neue Gast-Uploads erscheinen sofort in der Galerie (Security-Scan läuft im Hintergrund).',
                )
              : t(
                  'eventForm.fields.uploadVisibility.helpOff',
                  'Uploads werden zunächst geprüft und erscheinen nach Freigabe.',
                )}
          </Text>
        </MobileField>
      </MobileCard>

      <YStack space="$2" paddingBottom="$10">
        {!isEdit ? (
          <CTAButton
            label={t('eventForm.actions.saveDraft', 'Save as draft')}
            tone="ghost"
            onPress={back}
          />
        ) : null}
      </YStack>

      <FloatingActionButton
        label={
          saving
            ? t('eventForm.actions.saving', 'Saving…')
            : isEdit
              ? t('eventForm.actions.update', 'Update event')
              : t('eventForm.actions.create', 'Create event')
        }
        icon={isEdit ? Save : Check}
        onPress={() => handleSubmit()}
      />

      <LegalConsentSheet
        open={consentOpen}
        onClose={() => {
          if (consentBusy) return;
          setConsentOpen(false);
          setPendingPayload(null);
        }}
        onConfirm={handleConsentConfirm}
        busy={consentBusy}
        requireTerms={false}
        requireWaiver
        copy={{
          title: t('events.eventStartConsent.title', 'Before your first event'),
          description: t(
            'events.eventStartConsent.description',
            'Please confirm the immediate start of the digital service before creating your first event.',
          ),
          checkboxWaiver: t(
            'events.eventStartConsent.checkboxWaiver',
            'I expressly request that the digital service begins now and understand my right of withdrawal expires once the contract has been fully performed.',
          ),
          errorWaiver: t(
            'events.eventStartConsent.errorWaiver',
            'Please confirm the immediate start of the digital service and the early expiry of the right of withdrawal.',
          ),
          confirm: t('events.eventStartConsent.confirm', 'Create event'),
          cancel: t('events.eventStartConsent.cancel', 'Cancel'),
        }}
        t={t}
      />
    </MobileShell>
  );
}

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 isWaiverRequiredError(error: unknown): boolean {
  if (!isApiError(error)) {
    return false;
  }

  const metaErrors = error.meta?.errors;
  if (!metaErrors || typeof metaErrors !== 'object') {
    return false;
  }

  return 'accepted_waiver' in metaErrors;
}


function toDateTimeLocal(value?: string | null): string {
  if (!value) return '';
  const parsed = new Date(value);
  if (!Number.isNaN(parsed.getTime())) {
    return parsed.toISOString().slice(0, 16);
  }
  const fallback = value.replace(' ', 'T');
  return fallback.length >= 16 ? fallback.slice(0, 16) : '';
}

function resolveLocation(event: TenantEvent): string {
  const settings = (event.settings ?? {}) as Record<string, unknown>;
  const candidate =
    (settings.location as string | undefined) ??
    (settings.address as string | undefined) ??
    (settings.city as string | undefined);
  if (candidate && candidate.trim()) return candidate;
  return '';
}
