import React from 'react';
import { useTranslation } from 'react-i18next';
import { RefreshCcw } from 'lucide-react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Switch } from '@tamagui/switch';
import toast from 'react-hot-toast';
import { MobileShell, HeaderActionButton } from './components/MobileShell';
import { MobileCard, CTAButton, PillBadge, SkeletonCard } from './components/Primitives';
import { MobileSelect } from './components/FormControls';
import {
  DataExportSummary,
  downloadTenantDataExport,
  getEvents,
  listTenantDataExports,
  requestTenantDataExport,
  TenantEvent,
} from '../api';
import { getApiErrorMessage } from '../lib/apiError';
import { adminPath } from '../constants';
import { useBackNavigation } from './hooks/useBackNavigation';
import { formatRelativeTime } from './lib/relativeTime';
import { useAdminTheme } from './theme';
import i18n from '../i18n';
import { triggerDownloadFromBlob } from './invite-layout/export-utils';
import { hasInProgressExports } from './lib/dataExports';

const statusTone: Record<DataExportSummary['status'], 'success' | 'warning' | 'muted'> = {
  pending: 'warning',
  processing: 'warning',
  ready: 'success',
  failed: 'muted',
};

function formatBytes(bytes: number | null): string {
  if (!bytes || bytes <= 0) {
    return '—';
  }
  const units = ['B', 'KB', 'MB', 'GB', 'TB'];
  const index = Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(1024)));
  const value = bytes / Math.pow(1024, index);
  return `${value.toFixed(value >= 10 || index === 0 ? 0 : 1)} ${units[index]}`;
}

function formatEventName(event: TenantEvent | DataExportSummary['event'] | null): string {
  if (!event) {
    return '';
  }
  const name = event.name;
  if (typeof name === 'string') {
    return name;
  }
  if (name && typeof name === 'object') {
    return (name as Record<string, string>)[i18n.language] ?? name.de ?? name.en ?? event.slug ?? '';
  }
  return event.slug ?? '';
}

type DataExportsPanelProps = {
  variant?: 'page' | 'recap';
  event?: TenantEvent | null;
  onRefreshReady?: (refresh: () => void) => void;
};

export function DataExportsPanel({
  variant = 'page',
  event,
  onRefreshReady,
}: DataExportsPanelProps) {
  const { t } = useTranslation('management');
  const { textStrong, text, muted, danger } = useAdminTheme();
  const [exports, setExports] = React.useState<DataExportSummary[]>([]);
  const [events, setEvents] = React.useState<TenantEvent[]>([]);
  const isRecap = variant === 'recap';
  const [scope, setScope] = React.useState<'tenant' | 'event'>(isRecap ? 'event' : 'tenant');
  const [eventId, setEventId] = React.useState<number | null>(isRecap ? event?.id ?? null : null);
  const [includeMedia, setIncludeMedia] = React.useState(false);
  const [loading, setLoading] = React.useState(true);
  const [requesting, setRequesting] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);

  React.useEffect(() => {
    if (!isRecap) {
      return;
    }
    if (event?.id && eventId !== event.id) {
      setEventId(event.id);
    }
    if (event) {
      setEvents([event]);
    }
  }, [event, eventId, isRecap]);

  const load = React.useCallback(async () => {
    setLoading(true);
    try {
      const [exportRows, eventRows] = await Promise.all([
        listTenantDataExports(),
        isRecap ? Promise.resolve(event ? [event] : []) : getEvents({ force: true }),
      ]);
      setExports(exportRows);
      if (!isRecap) {
        setEvents(eventRows);
      } else if (eventRows.length > 0) {
        setEvents(eventRows);
      }
      setError(null);
    } catch (err) {
      setError(getApiErrorMessage(err, t('dataExports.errors.load', 'Exports konnten nicht geladen werden.')));
    } finally {
      setLoading(false);
    }
  }, [event, isRecap, t]);

  const refresh = React.useCallback(() => {
    void load();
  }, [load]);

  React.useEffect(() => {
    onRefreshReady?.(refresh);
  }, [onRefreshReady, refresh]);

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

  const hasInProgress = hasInProgressExports(exports);

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

    const interval = window.setInterval(() => {
      void load();
    }, 5000);

    return () => {
      window.clearInterval(interval);
    };
  }, [hasInProgress, load]);

  const handleRequest = async () => {
    if (requesting) {
      return;
    }

    const requestScope = isRecap ? 'event' : scope;
    const requestEventId = isRecap ? eventId : eventId;

    if (requestScope === 'event' && !requestEventId) {
      setError(t('dataExports.errors.eventRequired', 'Bitte wähle ein Event aus.'));
      return;
    }

    setRequesting(true);
    try {
      await requestTenantDataExport({
        scope: requestScope,
        eventId: requestScope === 'event' ? requestEventId ?? undefined : undefined,
        includeMedia,
      });
      toast.success(t('dataExports.actions.requested', 'Export wird vorbereitet.'));
      await load();
      setError(null);
    } catch (err) {
      setError(getApiErrorMessage(err, t('dataExports.errors.request', 'Export konnte nicht gestartet werden.')));
    } finally {
      setRequesting(false);
    }
  };

  const visibleExports = React.useMemo(() => {
    if (!isRecap) {
      return exports;
    }
    if (!event?.id) {
      return exports.filter((entry) => entry.scope === 'event');
    }
    return exports.filter((entry) => entry.scope === 'event' && entry.event?.id === event.id);
  }, [event?.id, exports, isRecap]);

  return (
    <>
      {error ? (
        <MobileCard>
          <Text fontWeight="700" color={danger}>
            {error}
          </Text>
          <CTAButton label={t('dataExports.actions.refresh', 'Refresh')} tone="ghost" onPress={refresh} />
        </MobileCard>
      ) : null}

      <MobileCard space="$2">
        <Text fontSize="$md" fontWeight="800" color={textStrong}>
          {t('dataExports.request.title', 'Export request')}
        </Text>
        <Text fontSize="$xs" color={muted}>
          {t('dataExports.request.hint', 'Export tenant data or a specific event archive.')}
        </Text>
        <YStack space="$2">
          {!isRecap ? (
            <XStack alignItems="center" justifyContent="space-between">
              <Text fontSize="$sm" color={text}>
                {t('dataExports.fields.scope', 'Scope')}
              </Text>
              <MobileSelect
                value={scope}
                onChange={(event) => setScope(event.target.value as 'tenant' | 'event')}
                compact
                style={{ minWidth: 140, maxWidth: 180 }}
              >
                <option value="tenant">{t('dataExports.scopes.tenant', 'Tenant')}</option>
                <option value="event">{t('dataExports.scopes.event', 'Event')}</option>
              </MobileSelect>
            </XStack>
          ) : (
            <XStack alignItems="center" justifyContent="space-between">
              <Text fontSize="$sm" color={text}>
                {t('dataExports.fields.event', 'Event')}
              </Text>
              <Text fontSize="$sm" color={textStrong}>
                {formatEventName(event) || event?.slug || t('dataExports.fields.eventPlaceholder', 'Choose event')}
              </Text>
            </XStack>
          )}
          {!isRecap && scope === 'event' ? (
            <XStack alignItems="center" justifyContent="space-between">
              <Text fontSize="$sm" color={text}>
                {t('dataExports.fields.event', 'Event')}
              </Text>
              <MobileSelect
                value={eventId ? String(eventId) : ''}
                onChange={(event) => setEventId(event.target.value ? Number(event.target.value) : null)}
                compact
                style={{ minWidth: 180, maxWidth: 220 }}
              >
                <option value="">{t('dataExports.fields.eventPlaceholder', 'Choose event')}</option>
                {events.map((event) => (
                  <option key={event.id} value={event.id}>
                    {formatEventName(event) || event.slug}
                  </option>
                ))}
              </MobileSelect>
            </XStack>
          ) : null}
          <XStack alignItems="center" justifyContent="space-between">
            <YStack>
              <Text fontSize="$sm" color={text}>
                {t('dataExports.fields.includeMedia', 'Include raw media')}
              </Text>
              <Text fontSize="$xs" color={muted}>
                {t('dataExports.fields.includeMediaHint', 'Bigger ZIP; choose when needed.')}
              </Text>
            </YStack>
            <Switch
              size="$3"
              checked={includeMedia}
              onCheckedChange={setIncludeMedia}
              aria-label={t('dataExports.fields.includeMedia', 'Include raw media')}
            >
              <Switch.Thumb />
            </Switch>
          </XStack>
          {hasInProgress ? (
            <Text fontSize="$xs" color={muted}>
              {t('dataExports.request.progress', 'Export is running. This list refreshes automatically.')}
            </Text>
          ) : null}
        </YStack>
        <CTAButton
          label={requesting ? t('dataExports.actions.requesting', 'Requesting...') : t('dataExports.actions.request', 'Request export')}
          onPress={handleRequest}
          disabled={requesting}
        />
      </MobileCard>

      <MobileCard space="$2">
        <Text fontSize="$md" fontWeight="800" color={textStrong}>
          {t('dataExports.history.title', 'Recent exports')}
        </Text>
        <Text fontSize="$xs" color={muted}>
          {t('dataExports.history.hint', 'Latest 10 exports for your tenant and events.')}
        </Text>
        {loading ? (
          <YStack space="$2">
            <SkeletonCard height={72} />
            <SkeletonCard height={72} />
          </YStack>
        ) : visibleExports.length === 0 ? (
          <Text fontSize="$sm" color={muted}>
            {t('dataExports.history.empty', 'No exports yet.')}
          </Text>
        ) : (
          <YStack space="$2">
            {visibleExports.map((entry) => (
              <MobileCard key={entry.id} space="$2">
                <XStack alignItems="center" justifyContent="space-between">
                  <YStack>
                    <Text fontSize="$sm" fontWeight="700" color={textStrong}>
                      {entry.scope === 'event'
                        ? t('dataExports.scopes.event', 'Event export')
                        : t('dataExports.scopes.tenant', 'Tenant export')}
                    </Text>
                    {entry.event ? (
                      <Text fontSize="$xs" color={muted}>
                        {formatEventName(entry.event)}
                      </Text>
                    ) : null}
                  </YStack>
                  <PillBadge tone={statusTone[entry.status]}>
                    {t(`dataExports.status.${entry.status}`, entry.status)}
                  </PillBadge>
                </XStack>
                <XStack alignItems="center" justifyContent="space-between">
                  <Text fontSize="$xs" color={muted}>
                    {formatRelativeTime(entry.created_at, { locale: i18n.language }) || '—'}
                  </Text>
                  <Text fontSize="$xs" color={muted}>
                    {formatBytes(entry.size_bytes)}
                  </Text>
                </XStack>
                {entry.include_media ? (
                  <PillBadge tone="muted">{t('dataExports.badges.includesMedia', 'Raw media')}</PillBadge>
                ) : null}
                {entry.download_url ? (
                  <CTAButton
                    label={t('dataExports.actions.download', 'Download')}
                    onPress={async () => {
                      if (!entry.download_url) {
                        return;
                      }
                      try {
                        const blob = await downloadTenantDataExport(entry.download_url);
                        const filename = `fotospiel-data-export-${entry.id}.zip`;
                        triggerDownloadFromBlob(blob, filename);
                        toast.success(t('dataExports.actions.downloaded', 'Download started.'));
                      } catch (err) {
                        toast.error(getApiErrorMessage(err, t('dataExports.errors.download', 'Download failed.')));
                      }
                    }}
                  />
                ) : entry.status === 'failed' ? (
                  <Text fontSize="$xs" color={danger}>
                    {entry.error_message ?? t('dataExports.errors.failed', 'Export failed.')}
                  </Text>
                ) : null}
              </MobileCard>
            ))}
          </YStack>
        )}
      </MobileCard>
    </>
  );
}

export default function MobileDataExportsPage() {
  const { t } = useTranslation('management');
  const { textStrong } = useAdminTheme();
  const back = useBackNavigation(adminPath('/mobile/profile'));
  const [refresh, setRefresh] = React.useState<null | (() => void)>(null);

  return (
    <MobileShell
      activeTab="profile"
      title={t('dataExports.title', 'Data exports')}
      onBack={back}
      headerActions={
        <HeaderActionButton onPress={() => refresh?.()} ariaLabel={t('common.refresh', 'Refresh')}>
          <RefreshCcw size={18} color={textStrong} />
        </HeaderActionButton>
      }
    >
      <DataExportsPanel onRefreshReady={setRefresh} />
    </MobileShell>
  );
}
