import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import {
  fetchEvent,
  EventData,
  FetchEventError,
  FetchEventErrorCode,
} from '../services/eventApi';

type EventDataStatus = 'loading' | 'ready' | 'error';

interface UseEventDataResult {
  event: EventData | null;
  status: EventDataStatus;
  loading: boolean;
  error: string | null;
  errorCode: FetchEventErrorCode | null;
  token: string | null;
}

const NO_TOKEN_ERROR_MESSAGE = 'Es wurde kein Einladungscode übergeben.';
const eventCache = new Map<string, EventData>();

export function useEventData(): UseEventDataResult {
  const { token } = useParams<{ token: string }>();
  const cachedEvent = token ? eventCache.get(token) ?? null : null;
  const [event, setEvent] = useState<EventData | null>(cachedEvent);
  const [status, setStatus] = useState<EventDataStatus>(token ? (cachedEvent ? 'ready' : 'loading') : 'error');
  const [errorMessage, setErrorMessage] = useState<string | null>(token ? null : NO_TOKEN_ERROR_MESSAGE);
  const [errorCode, setErrorCode] = useState<FetchEventErrorCode | null>(token ? null : 'invalid_token');

  useEffect(() => {
    if (!token) {
      setEvent(null);
      setStatus('error');
      setErrorCode('invalid_token');
      setErrorMessage(NO_TOKEN_ERROR_MESSAGE);
      return;
    }

    let cancelled = false;

    const loadEvent = async () => {
      const cached = eventCache.get(token) ?? null;
      if (!cached) {
        setStatus('loading');
      }
      setErrorCode(null);
      setErrorMessage(null);

      try {
        const eventData = await fetchEvent(token);
        if (cancelled) {
          return;
        }

        eventCache.set(token, eventData);
        setEvent(eventData);
        setStatus('ready');
      } catch (err) {
        if (cancelled) {
          return;
        }

        if (cached) {
          setEvent(cached);
          setStatus('ready');
          return;
        }
        setEvent(null);
        setStatus('error');

        if (err instanceof FetchEventError) {
          setErrorCode(err.code);
          setErrorMessage(err.message);
        } else if (err instanceof Error) {
          setErrorCode('unknown');
          setErrorMessage(err.message || 'Event konnte nicht geladen werden.');
        } else {
          setErrorCode('unknown');
          setErrorMessage('Event konnte nicht geladen werden.');
        }
      }
    };

    loadEvent();

    return () => {
      cancelled = true;
    };
  }, [token]);

  return {
    event,
    status,
    loading: status === 'loading',
    error: errorMessage,
    errorCode,
    token: token ?? null,
  };
}
