import rawManifest from '@/contracts/phase9/route-manifest.json';
import {
  isThemePreference,
  themePreferences,
  type ThemePreference,
} from '@/lib/theme/config';
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' | 'sign-in' | 'forgot-password' | 'reset-password' | 'privacy' | 'terms' | 'accessibility';

export const defaultLocale: Locale = 'en';
export const defaultMode: ThemePreference = 'system';
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', 'sign-in', 'forgot-password', 'reset-password', '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 {
  return localizedModePath(routeId, locale, defaultMode);
}

export function localizedModePath(
  routeId: RouteId,
  locale: Locale,
  mode: ThemePreference,
): 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}/${mode}/${slug}` : `/${locale}/${mode}`;
}

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(
    localizedModePath(routeId, targetLocale, modeFromPathname(current.pathname)),
    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 modeSwitchUrl(current: URL, targetMode: ThemePreference, routeId: RouteId): URL {
  const locale = localeFromPathname(current.pathname) ?? defaultLocale;
  const target = new URL(localizedModePath(routeId, locale, targetMode), current.origin);
  target.search = current.search;

  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 routeIdFromAnyLocaleSlug(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) =>
    locales.some((locale) => item.slugs[locale] === normalized),
  );
  return route?.id ?? null;
}

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

export function localeFromPathname(pathname: string): Locale | null {
  const [localeValue] = pathname.split('/').filter(Boolean);
  return isLocale(localeValue) ? localeValue : null;
}

export function modeFromPathname(pathname: string): ThemePreference {
  const [, modeValue] = pathname.split('/').filter(Boolean);
  return isThemePreference(modeValue) ? modeValue : defaultMode;
}

export function isMode(value: unknown): value is ThemePreference {
  return isThemePreference(value);
}

export function localizedUrl(
  origin: URL,
  routeId: RouteId,
  locale: Locale,
  mode: ThemePreference = defaultMode,
): URL {
  return new URL(localizedModePath(routeId, locale, mode), origin);
}

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

export { themePreferences as modes };
