import type { LocaleCode } from '../i18n/messages';

export interface GalleryBranding {
  primary_color: string;
  secondary_color: string;
  background_color: string;
  surface_color?: string;
  mode?: 'light' | 'dark' | 'auto';
  palette?: {
    primary?: string | null;
    secondary?: string | null;
    background?: string | null;
    surface?: string | null;
  } | null;
}

export interface GalleryMetaResponse {
  event: {
    id: number;
    name: string;
    slug?: string | null;
    description?: string | null;
    gallery_expires_at?: string | null;
    guest_downloads_enabled?: boolean;
    guest_sharing_enabled?: boolean;
  };
  branding: GalleryBranding;
}

export interface GalleryPhotoResource {
  id: number;
  thumbnail_url: string | null;
  full_url: string | null;
  download_url: string;
  likes_count: number;
  guest_name?: string | null;
  created_at?: string | null;
}

export interface GalleryPhotosResponse {
  data: GalleryPhotoResource[];
  next_cursor: string | null;
}

async function handleResponse<T>(response: Response): Promise<T> {
  if (response.status === 204) {
    return {} as T;
  }

  const data = await response.json().catch(() => null);

  if (!response.ok) {
    const errorPayload = data as { error?: { message?: string; code?: unknown } } | null;
    const error = new Error(errorPayload?.error?.message ?? 'Request failed') as Error & { code?: unknown };
    error.code = errorPayload?.error?.code ?? response.status;
    throw error;
  }

  return data as T;
}

function coerceLocalized(value: unknown, fallback: string): string {
  if (typeof value === 'string' && value.trim() !== '') {
    return value;
  }

  if (value && typeof value === 'object') {
    const obj = value as Record<string, unknown>;
    const preferred = ['de', 'en'];
    for (const key of preferred) {
      const candidate = obj[key];
      if (typeof candidate === 'string' && candidate.trim() !== '') {
        return candidate;
      }
    }
    const firstString = Object.values(obj).find((candidate) => typeof candidate === 'string' && candidate.trim() !== '');
    if (typeof firstString === 'string') {
      return firstString;
    }
  }

  return fallback;
}

export async function fetchGalleryMeta(token: string, locale?: LocaleCode): Promise<GalleryMetaResponse> {
  const params = new URLSearchParams();
  if (locale) params.set('locale', locale);

  const response = await fetch(`/api/v1/gallery/${encodeURIComponent(token)}${params.toString() ? `?${params.toString()}` : ''}`, {
    headers: {
      'Accept': 'application/json',
    },
    credentials: 'omit',
  });

  const data = await handleResponse<GalleryMetaResponse>(response);

  if (data?.event) {
    data.event = {
      ...data.event,
      name: coerceLocalized((data.event as any).name, 'Fotospiel Event'),
      description: coerceLocalized((data.event as any).description, ''),
    };
  }

  return data;
}

export async function fetchGalleryPhotos(token: string, cursor?: string | null, limit = 30): Promise<GalleryPhotosResponse> {
  const params = new URLSearchParams();
  params.set('limit', String(limit));
  if (cursor) {
    params.set('cursor', cursor);
  }

  const response = await fetch(`/api/v1/gallery/${encodeURIComponent(token)}/photos?${params.toString()}`, {
    headers: {
      'Accept': 'application/json',
    },
    credentials: 'omit',
  });

  return handleResponse<GalleryPhotosResponse>(response);
}
