import { fetchGraphQL } from "../client";
import { SECTIONS_FIELD, SECTIONS_FRAGMENTS, SEO_FIELDS } from "../fragments";
import { type Locale } from "@/config/i18nRoutes";
import { WP_I18N_ENABLED } from "../flags";
import { pickLang } from "../i18n";
import { isExcludedUri } from "../hardcodedUris";
import type { WpPage } from "../types";

// Champs i18n (Polylang) ajoutés uniquement quand WP_I18N_ENABLED — sinon le
// schéma GraphQL ne connaît pas `language`/`translations` et la requête échoue.
const LANG_FIELDS = WP_I18N_ENABLED ? `language { code slug }` : ``;
const PAGE_TRANSLATIONS = WP_I18N_ENABLED
  ? `translations { id title uri language { code slug } seo ${SEO_FIELDS} ${SECTIONS_FIELD} }`
  : ``;

const PAGE_QUERY = /* GraphQL */ `
  ${SECTIONS_FRAGMENTS}
  query GetPage($uri: ID!) {
    page(id: $uri, idType: URI) {
      id
      title
      uri
      ${LANG_FIELDS}
      seo ${SEO_FIELDS}
      ${SECTIONS_FIELD}
      ${PAGE_TRANSLATIONS}
    }
  }
`;

/**
 * Pages « listing » qui embarquent du contenu d'autres CPT : elles s'abonnent à
 * des tags `listing:*:{lang}`. Au save d'un produit/référence/industrie dans une
 * langue, WordPress émet le tag `listing:*:{lang}` correspondant → seules ces
 * pages d'agrégation (dans cette langue) sont revalidées.
 * À garder aligné avec cvb_listing_tags_for_type() côté mu-plugin.
 */
const LISTING_TAGS_BY_URI: Record<string, string[]> = {
  "/accueil": ["listing:produits", "listing:references", "listing:secteurs"],
  "/references": ["listing:references"],
  "/industrie": ["listing:secteurs"],
};

/**
 * Récupère une page native WP par URI FR canonique (ex. "/accueil", "/contact").
 * Pour en/es, on récupère la page FR + ses traductions et on choisit la locale.
 */
export async function getWpPage(uri: string, locale: Locale = "fr"): Promise<WpPage | null> {
  // FR : tags historiques inchangés. EN/ES : tags qualifiés par langue.
  const qualify = (t: string) => (locale === "fr" ? t : `${t}:${locale}`);
  const listing = (LISTING_TAGS_BY_URI[uri] ?? []).map(qualify);
  const data = await fetchGraphQL<{ page: WpPage | null }>(
    PAGE_QUERY,
    { uri },
    { tags: ["page", qualify(`page:${uri}`), ...listing] }
  );
  return pickLang(data.page ?? null, locale);
}

const ALL_PAGE_URIS_QUERY = /* GraphQL */ `
  query GetAllPageUris($after: String) {
    pages(first: 100, after: $after, where: { status: PUBLISH }) {
      pageInfo {
        hasNextPage
        endCursor
      }
      nodes {
        uri
        ${WP_I18N_ENABLED ? "language { slug }" : ""}
      }
    }
  }
`;

/** Liste les URIs de pages publiées dans une langue (filtrage langue côté JS). */
export async function getAllWpPageUris(locale: Locale = "fr"): Promise<string[]> {
  const uris: string[] = [];
  let after: string | null = null;
  let hasNextPage = true;

  while (hasNextPage) {
    const data = await fetchGraphQL<{
      pages: {
        pageInfo: { hasNextPage: boolean; endCursor: string | null };
        nodes: { uri: string | null; language?: { slug?: string | null } | null }[] | null;
      } | null;
    }>(ALL_PAGE_URIS_QUERY, { after }, { tags: ["page"] });

    const pages = data.pages;
    for (const node of pages?.nodes ?? []) {
      if (!node.uri) continue;
      if (WP_I18N_ENABLED && node.language?.slug && node.language.slug !== locale) continue;
      if (isExcludedUri(node.uri)) continue; // pages de test/démo WP → ni build ni sitemap
      uris.push(node.uri);
    }
    hasNextPage = Boolean(pages?.pageInfo?.hasNextPage);
    after = pages?.pageInfo?.endCursor ?? null;
  }

  return uris;
}
