import React from 'react';
import { useQuery } from '@tanstack/react-query';

import { getEvents, type TenantEvent } from '../api';
import { useAuth } from '../auth/context';

const STORAGE_KEY = 'tenant-admin.active-event';

export interface EventContextValue {
  events: TenantEvent[];
  isLoading: boolean;
  isError: boolean;
  activeEvent: TenantEvent | null;
  activeSlug: string | null;
  hasEvents: boolean;
  hasMultipleEvents: boolean;
  selectEvent: (slug: string | null) => void;
  refetch: () => void;
}

const EventContext = React.createContext<EventContextValue | undefined>(undefined);

export function EventProvider({ children }: { children: React.ReactNode }) {
  const { status } = useAuth();
  const [manualEvents, setManualEvents] = React.useState<TenantEvent[]>([]);
  const [manualAttempted, setManualAttempted] = React.useState(false);
  const [storedSlug, setStoredSlug] = React.useState<string | null>(() => {
    if (typeof window === 'undefined') {
      return null;
    }
    return window.localStorage.getItem(STORAGE_KEY);
  });

  const authReady = status === 'authenticated';

  const {
    data: fetchedEvents = [],
    isLoading: queryLoading,
    isError,
    refetch,
  } = useQuery<TenantEvent[]>({
    queryKey: ['tenant-events'],
    queryFn: async () => {
      try {
        return await getEvents({ force: true });
      } catch (error) {
        console.warn('[EventContext] Failed to fetch events', error);
        throw error;
      }
    },
    staleTime: 60 * 1000,
    enabled: authReady,
    initialData: [],
  });

  const events = React.useMemo(
    () => (authReady ? (manualEvents.length ? manualEvents : fetchedEvents) : []),
    [authReady, fetchedEvents, manualEvents]
  );
  const isLoading = authReady ? queryLoading || (!manualAttempted && manualEvents.length === 0 && fetchedEvents.length === 0) : status === 'loading';

  React.useEffect(() => {
    if (!authReady || manualAttempted || queryLoading) {
      return;
    }
    if (fetchedEvents.length > 0 && !isError) {
      return;
    }
    setManualAttempted(true);
    getEvents({ force: true })
      .then((list) => {
        setManualEvents(list ?? []);
      })
      .catch(() => {
        setManualEvents([]);
      });
  }, [authReady, fetchedEvents.length, isError, manualAttempted, queryLoading]);

  React.useEffect(() => {
    if (!events.length || typeof window === 'undefined') {
      return;
    }

    const hasStored = Boolean(storedSlug);
    const slugExists = hasStored && events.some((event) => event.slug === storedSlug);

    if (!slugExists) {
      const shouldAutoselect = events.length === 1;
      const fallbackSlug = shouldAutoselect ? events[0]?.slug : null;
      setStoredSlug(fallbackSlug);
      if (fallbackSlug) {
        window.localStorage.setItem(STORAGE_KEY, fallbackSlug);
      } else {
        window.localStorage.removeItem(STORAGE_KEY);
      }
    }
  }, [events, storedSlug]);

  const activeEvent = React.useMemo(() => {
    if (!events.length) {
      return null;
    }

    const matched = events.find((event) => event.slug && event.slug === storedSlug);
    if (matched) {
      return matched;
    }

    // Only auto-select the single available event. When multiple events exist and
    // no stored slug is present we intentionally return null to let the UI prompt
    // for a selection.
    if (events.length === 1) {
      return events[0];
    }

    return null;
  }, [events, storedSlug]);

  const hasEvents = events.length > 0;
  const hasMultipleEvents = events.length > 1;
  const activeSlug = activeEvent?.slug ?? null;

  const selectEvent = React.useCallback((slug: string | null) => {
    setStoredSlug(slug);
    if (typeof window !== 'undefined') {
      if (slug) {
        window.localStorage.setItem(STORAGE_KEY, slug);
      } else {
        window.localStorage.removeItem(STORAGE_KEY);
      }
    }
  }, []);

  const value = React.useMemo<EventContextValue>(
    () => ({
      events,
      isLoading,
      isError,
      activeEvent,
      activeSlug,
      hasEvents,
      hasMultipleEvents,
      selectEvent,
      refetch,
    }),
    [events, isLoading, isError, activeEvent, activeSlug, hasEvents, hasMultipleEvents, selectEvent, refetch]
  );

  return <EventContext.Provider value={value}>{children}</EventContext.Provider>;
}

export function useEventContext(): EventContextValue {
  const ctx = React.useContext(EventContext);
  if (!ctx) {
    throw new Error('useEventContext must be used within an EventProvider');
  }
  return ctx;
}
