import rawManifest from '@/contracts/phase9/route-manifest.json';
import { z } from 'zod';

export const locales = ['en', 'fr', 'ar'] as const;
export type Locale = (typeof locales)[number];
export type Direction = 'ltr' | 'rtl';
export type RouteId = 'home' | 'login' | 'privacy' | 'terms' | 'accessibility';

export const defaultLocale: Locale = 'en';
export const localeCookie = 'hpc-locale';
export const localeStorageKey = 'hpc.locale';
export const localeCookieMaxAgeSeconds = 31_536_000;
export const directionByLocale: Record<Locale, Direction> = {
  en: 'ltr',
  fr: 'ltr',
  ar: 'rtl',
};

const localeSchema = z.enum(locales);
const routeSchema = z.object({
  id: z.enum(['home', 'login', 'privacy', 'terms', 'accessibility']),
  slugs: z.object({ en: z.string(), fr: z.string(), ar: z.string() }),
  indexable: z.boolean(),
  hashes: z.array(z.string()),
});
const routeManifestSchema = z.object({
  version: z.string(),
  defaultLocale: localeSchema,
  locales: z.array(localeSchema).length(locales.length),
  rootDetection: z.boolean(),
  routes: z.array(routeSchema),
  switching: z.object({
    preserveQueryAllowlist: z.array(z.string()),
    preserveValidHash: z.boolean(),
    dropUnknownQuery: z.boolean(),
  }),
  hreflang: z.object({
    values: z.array(localeSchema),
    xDefaultLocale: localeSchema,
    selfCanonical: z.boolean(),
  }),
});

export const routeManifest = routeManifestSchema.parse(rawManifest);
export const campaignQueryAllowlist = routeManifest.switching.preserveQueryAllowlist;

export function isLocale(value: unknown): value is Locale {
  return typeof value === 'string' && (locales as readonly string[]).includes(value);
}

export function getDirection(locale: Locale): Direction {
  return directionByLocale[locale];
}

export function localizedPath(routeId: RouteId, locale: Locale): string {
  const route = routeManifest.routes.find((item) => item.id === routeId);
  if (!route) {
    throw new Error(`Unknown route ID: ${routeId}`);
  }
  const slug = route.slugs[locale];
  return slug.length > 0 ? `/${locale}/${slug}` : `/${locale}`;
}

export function routeById(routeId: RouteId) {
  const route = routeManifest.routes.find((item) => item.id === routeId);
  if (!route) {
    throw new Error(`Unknown route ID: ${routeId}`);
  }
  return route;
}

export function localeFromAcceptLanguage(headerValue: string | null): Locale {
  if (!headerValue) return defaultLocale;

  const requested = headerValue
    .split(',')
    .map((entry) => {
      const [tag = '', ...parameters] = entry.trim().split(';');
      const qualityParameter = parameters.find((parameter) => parameter.trim().startsWith('q='));
      const quality = qualityParameter ? Number(qualityParameter.trim().slice(2)) : 1;
      return { tag: tag.toLowerCase(), quality: Number.isFinite(quality) ? quality : 0 };
    })
    .sort((a, b) => b.quality - a.quality);

  for (const request of requested) {
    const base = request.tag.split('-')[0];
    if (isLocale(base)) return base;
  }
  return defaultLocale;
}

export function localeSwitchUrl(current: URL, targetLocale: Locale, routeId: RouteId): URL {
  const target = new URL(localizedPath(routeId, targetLocale), current.origin);
  for (const key of campaignQueryAllowlist) {
    const value = current.searchParams.get(key);
    if (value !== null) target.searchParams.set(key, value);
  }

  const route = routeById(routeId);
  const hash = current.hash.replace(/^#/, '');
  if (routeManifest.switching.preserveValidHash && route.hashes.includes(hash)) {
    target.hash = hash;
  }
  return target;
}

export function routeIdFromSlug(locale: Locale, slug: string): RouteId | null {
  let decoded: string;
  try {
    decoded = decodeURIComponent(slug);
  } catch {
    return null;
  }
  const normalized = decoded.replace(/^\/+|\/+$/g, '');
  const route = routeManifest.routes.find((item) => item.slugs[locale] === normalized);
  return route?.id ?? null;
}

export function routeIdFromPathname(pathname: string): RouteId | null {
  const [localeValue, ...segments] = pathname.split('/').filter(Boolean);
  if (!isLocale(localeValue)) return null;
  if (segments.length === 0) return 'home';
  return routeIdFromSlug(localeValue, segments.join('/'));
}

export function localizedUrl(origin: URL, routeId: RouteId, locale: Locale): URL {
  return new URL(localizedPath(routeId, locale), origin);
}

export function hreflangMap(origin: URL, routeId: RouteId): Record<string, string> {
  const entries = locales.map((locale) => [
    locale,
    new URL(localizedPath(routeId, locale), origin).href,
  ]);
  entries.push([
    'x-default',
    new URL(localizedPath(routeId, routeManifest.hreflang.xDefaultLocale), origin).href,
  ]);
  return Object.fromEntries(entries);
}
