import { cookies } from "next/headers";

// Retrieve the base WordPress API URL from environment variables (.env)
const API_URL = process.env.NEXT_PUBLIC_API_BASE_URL;

export type HttpMethod = "GET" | "POST";

export interface FetchPageDataOptions {
  revalidate?: number;
  method?: HttpMethod;
}

// Module-level cache for English to French blog slug mapping
let cachedBlogSlugMap: Record<string, string> | null = null;

async function getBlogSlugMap(
  cleanUrl: string,
  httpMethod: HttpMethod,
  revalidate: number
): Promise<Record<string, string>> {
  if (cachedBlogSlugMap) return cachedBlogSlugMap;
  try {
    const fetchSingle = async (url: string) => {
      const res = await fetch(url, {
        method: httpMethod,
        headers: { "Content-Type": "application/json" },
        next: { revalidate },
      });
      if (res.ok) return await res.json();
      return null;
    };

    const separator = cleanUrl.includes("?") ? "&" : "?";
    const [resEn, resFr] = await Promise.all([
      fetchSingle(`${cleanUrl}pages/blogs${separator}lang=en`),
      fetchSingle(`${cleanUrl}pages/blogs${separator}lang=fr`),
    ]);

    const cardsEn = resEn?.data?.blogs?.blog_cards || [];
    const cardsFr = resFr?.data?.blogs?.blog_cards || [];

    const map: Record<string, string> = {};
    cardsEn.forEach((cEn: any, idx: number) => {
      const cFr = cardsFr[idx];
      if (cFr && cFr.slug && cEn && cEn.slug) {
        map[cEn.slug] = cFr.slug;
        map[cFr.slug] = cEn.slug;
      }
    });

    cachedBlogSlugMap = map;
    return map;
  } catch (e) {
    return {};
  }
}



/**
 * Generic service to fetch layout or page JSON data from WordPress backend.
 * Automatically appends the selected language (lang=en or lang=fr) to all API requests.
 */
export async function fetchPageData<T>(
  slug: string,
  options?: FetchPageDataOptions
): Promise<T>;

export async function fetchPageData<T>(
  slug: string,
  revalidate?: number,
  method?: HttpMethod
): Promise<T>;

export async function fetchPageData<T>(
  slug: string,
  revalidateOrOptions: number | FetchPageDataOptions = 0,
  method: HttpMethod = "POST"
): Promise<T> {
  let revalidate = 0;
  let httpMethod: HttpMethod = method;

  if (typeof revalidateOrOptions === "object" && revalidateOrOptions !== null) {
    if (typeof revalidateOrOptions.revalidate === "number") {
      revalidate = revalidateOrOptions.revalidate;
    }
    if (revalidateOrOptions.method) {
      httpMethod = revalidateOrOptions.method;
    }
  } else if (typeof revalidateOrOptions === "number") {
    revalidate = revalidateOrOptions;
  }

  if (!API_URL) {
    throw new Error("NEXT_PUBLIC_API_BASE_URL is not defined");
  }

  // 1. Language Resolution (Defaults to French "fr")
  let lang = "fr";
  try {
    const cookieStore = await cookies();
    const langCookie = cookieStore.get("lang")?.value?.toLowerCase();
    if (langCookie === "en" || langCookie === "fr") {
      lang = langCookie;
    }
  } catch (error) {
    // Falls back safely to "fr" during static build (SSG)
  }

  const cleanUrl = API_URL.trim().replace(/^['"]|['"]$/g, "");

  const fetchSingleEndpoint = async (url: string): Promise<any> => {
    const maxRetries = 3;
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        const fetchOptions: RequestInit = {
          method: httpMethod,
          headers: {
            "Content-Type": "application/json",
          },
          cache: revalidate === 0 ? "no-store" : undefined,
          next: revalidate > 0 ? { revalidate } : undefined,
        };
        const response = await fetch(url, fetchOptions);

        if (response.ok) {
          return await response.json();
        }

        if (response.status >= 500 && attempt < maxRetries) {
          await new Promise((resolve) => setTimeout(resolve, attempt * 600));
          continue;
        }
        break;
      } catch (error) {
        if (attempt < maxRetries) {
          await new Promise((resolve) => setTimeout(resolve, attempt * 600));
        }
      }
    }
    return null;
  };

  const separator = cleanUrl.includes("?") || slug.includes("?") ? "&" : "?";

  const isValidResult = (res: any): boolean => {
    if (!res || typeof res !== "object") return false;
    if (res.code === "page_not_found" || res.message === "Page not found") return false;
    if (res.data?.status === 404 || res.data?.status === "404") return false;
    if (res.status === false && !res.data) return false;
    return true;
  };

  // Special handling for blog post detail pages ("pages/blog/:slug")
  if (slug.startsWith("pages/blog/")) {
    const rawPostSlug = slug.replace(/^pages\/blog\//, "");

    // 1. Direct fetch in the requested language ONLY
    const targetUrl = `${cleanUrl}pages/blog/${rawPostSlug}${separator}lang=${lang}`;
    const resultDirect = await fetchSingleEndpoint(targetUrl);
    if (
      resultDirect &&
      (resultDirect.id || resultDirect.title || resultDirect.post_content)
    ) {
      return resultDirect as T;
    }

    // 2. Resolve mapped slug in requested language ONLY
    const blogMap = await getBlogSlugMap(cleanUrl, httpMethod, revalidate);
    const mappedSlug = blogMap[rawPostSlug];

    if (mappedSlug) {
      const urlMapped = `${cleanUrl}pages/blog/${mappedSlug}${separator}lang=${lang}`;
      const resultMapped = await fetchSingleEndpoint(urlMapped);
      if (
        resultMapped &&
        (resultMapped.id || resultMapped.title || resultMapped.post_content)
      ) {
        return resultMapped as T;
      }
    }

    // Strictly return empty object if post does not exist in requested language (do NOT fallback to alternate language)
    return { data: {} } as T;
  }

  // Build dynamic candidate slugs for the requested language
  const baseCandidates: string[] = [slug];

  if (slug.includes("aesthetic")) {
    const cos = slug.replace("aesthetic", "cosmetic");
    baseCandidates.push(cos);
    if (slug === "pages/aesthetic") {
      baseCandidates.push("pages/cosmetic-landing");
      baseCandidates.push("pages/aesthetic-landing");
    }
  } else if (slug.includes("cosmetic")) {
    const aes = slug.replace("cosmetic", "aesthetic");
    baseCandidates.push(aes);
    if (slug === "pages/cosmetic" || slug === "pages/cosmetic-landing") {
      baseCandidates.push("pages/aesthetic");
    }
  }

  const candidates: string[] = [];

  for (const s of baseCandidates) {
    if (!candidates.includes(s)) candidates.push(s);

    if (s.endsWith("-clinic")) {
      const stripped = s.replace(/-clinic$/, "");
      if (!candidates.includes(stripped)) candidates.push(stripped);
    } else {
      const appended = `${s}-clinic`;
      if (!candidates.includes(appended)) candidates.push(appended);
    }

    if (s.endsWith("-fr")) {
      const strippedFr = s.replace(/-fr$/, "");
      if (!candidates.includes(strippedFr)) candidates.push(strippedFr);
    } else {
      const appendedFr = `${s}-fr`;
      if (!candidates.includes(appendedFr)) candidates.push(appendedFr);
    }
  }

  // Fetch candidates in requested language ONLY
  for (const candSlug of candidates) {
    const targetUrl = `${cleanUrl}${candSlug}${separator}lang=${lang}`;
    const result = await fetchSingleEndpoint(targetUrl);
    if (isValidResult(result)) {
      return result as T;
    }
  }

  // Strictly return empty object if page does not exist in requested language
  return { data: {} } as T;
}