import { API_BASE_URL } from '~/lib/api';
import { logger } from '~/lib/logger';

export interface AvailableLanguage {
  code: string;
  label: string;
  country: string;
  currency: string;
  currencySymbol: string;
}

const CACHE_KEY = 'nomadic-available-languages';
const CACHE_TTL_MS = 10 * 60 * 1000;

interface CachedLanguages {
  data: AvailableLanguage[];
  timestamp: number;
}

// Fallback used when the API is unreachable
const FALLBACK_LANGUAGES: AvailableLanguage[] = [
  { code: 'en', label: 'English', country: 'United States', currency: 'USD', currencySymbol: '$' },
  { code: 'sp', label: 'Spanish', country: 'Spain', currency: 'EUR', currencySymbol: '€' },
  { code: 'th', label: 'Thai', country: 'Thailand', currency: 'THB', currencySymbol: '฿' },
];

let resolvedLanguages: AvailableLanguage[] | null = null;
let inflightRequest: Promise<AvailableLanguage[]> | null = null;
const subscribers = new Set<(langs: AvailableLanguage[]) => void>();

const getCached = (): CachedLanguages | null => {
  if (typeof window === 'undefined') return null;
  try {
    const raw = localStorage.getItem(CACHE_KEY);
    if (!raw) return null;
    return JSON.parse(raw) as CachedLanguages;
  } catch {
    return null;
  }
};

const setCache = (data: AvailableLanguage[]): void => {
  if (typeof window === 'undefined') return;
  try {
    localStorage.setItem(CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));
  } catch { /* ignore */ }
};

const notify = (data: AvailableLanguage[]) => {
  resolvedLanguages = data;
  subscribers.forEach(fn => fn(data));
};

async function fetchLanguagesFromAPI(): Promise<AvailableLanguage[] | null> {
  try {
    const res = await fetch(`${API_BASE_URL}/translations/languages`, {
      headers: { Accept: 'application/json' },
    });
    if (!res.ok) return null;
    const json = await res.json();
    if (json?.data && Array.isArray(json.data)) {
      return json.data as AvailableLanguage[];
    }
    if (Array.isArray(json)) {
      return json as AvailableLanguage[];
    }
    return null;
  } catch {
    return null;
  }
}

export async function loadAvailableLanguages(): Promise<void> {
  if (resolvedLanguages) return;

  const cached = getCached();
  if (cached) {
    notify(cached.data);
    if (Date.now() - cached.timestamp < CACHE_TTL_MS) return;
  }

  if (inflightRequest) {
    await inflightRequest;
    return;
  }

  inflightRequest = fetchLanguagesFromAPI();
  try {
    const fresh = await inflightRequest;
    if (fresh && fresh.length > 0) {
      setCache(fresh);
      notify(fresh);
    } else if (!resolvedLanguages) {
      notify(FALLBACK_LANGUAGES);
    }
  } finally {
    inflightRequest = null;
  }
}

export function getAvailableLanguages(): AvailableLanguage[] {
  return resolvedLanguages || FALLBACK_LANGUAGES;
}

export function getLanguageCodes(): string[] {
  return getAvailableLanguages().map(l => l.code);
}

export function isValidLanguage(code: string): boolean {
  return getAvailableLanguages().some(l => l.code === code);
}

export function subscribeLanguages(fn: (langs: AvailableLanguage[]) => void): () => void {
  subscribers.add(fn);
  return () => subscribers.delete(fn);
}

// Server-side helper: fetch all translation languages
export async function fetchAllTranslationsForLoader(
  apiBaseUrl: string
): Promise<Record<string, any>> {
  const codes = getLanguageCodes();
  const results = await Promise.all(
    codes.map(async (lang) => {
      try {
        const res = await fetch(`${apiBaseUrl}/translations/${lang}`, {
          headers: { Accept: 'application/json' },
        });
        if (!res.ok) {
          logger.warn(`Translation API returned ${res.status} for ${lang}`);
          return [lang, {}] as const;
        }
        const data = await res.json();
        return [lang, data?.translations || {}] as const;
      } catch (err) {
        logger.warn(`Failed to fetch translations for ${lang}:`, err);
        return [lang, {}] as const;
      }
    })
  );
  return Object.fromEntries(results);
}
