// ----------------------------------------------------------------------------
// Strapi API Client
// ----------------------------------------------------------------------------
// Reusable utility functions for interacting with the Strapi CMS.
// Includes generic fetcher, ping, and helpers for fetching specific resources.
// ----------------------------------------------------------------------------

import { DEFAULT_LOCALE, getCurrentLocale, type SupportedLocale } from "./locale";

type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";

// Ensure no trailing slash in base URL
const STRAPI_URL =
  process.env.NEXT_PUBLIC_STRAPI_URL?.replace(/\/+$/, "") || "";

function getStrapiToken() {
  return process.env.NEXT_PUBLIC_STRAPI_TOKEN || process.env.STRAPI_API_TOKEN || "";
}

function appendLocale(endpoint: string, locale?: SupportedLocale | "all") {
  if (endpoint.includes("locale=")) return endpoint;

  const selectedLocale = locale || getCurrentLocale() || DEFAULT_LOCALE;
  const separator = endpoint.includes("?") ? "&" : "?";
  return `${endpoint}${separator}locale=${selectedLocale}`;
}

/**
 * Generic fetch function for interacting with Strapi REST API.
 *
 * @template T Expected response type
 * @param {string} endpoint API path, e.g., "/api/sekcje-strona-glownas"
 * @param {RequestInit} options Fetch options (headers, body, etc.)
 * @param {HttpMethod} method HTTP method (default: GET)
 * @returns {Promise<T>} Parsed JSON response
 * @throws Will throw if the request fails or response is not OK
 */
export async function strapiFetch<T = any>(
  endpoint: string,
  options: RequestInit = {},
  method: HttpMethod = "GET",
  locale?: SupportedLocale | "all"
): Promise<T> {
  const localizedEndpoint = method === "GET" ? appendLocale(endpoint, locale) : endpoint;
  const url = `${STRAPI_URL}${localizedEndpoint.startsWith("/") ? "" : "/"}${localizedEndpoint}`;
  const TOKEN = getStrapiToken();

  try {
    const res = await fetch(url, {
      method,
      headers: {
        "Content-Type": "application/json",
        ...(TOKEN ? { Authorization: `Bearer ${TOKEN}` } : {}),
        ...(options.headers || {}),
      },
      ...options,
    });

    if (!res.ok) {
      throw new Error(`Strapi error ${res.status} on ${endpoint}`);
    }

    const json = await res.json();
    return json as T;
  } catch (err) {
    console.error("Strapi fetch failed:", err);
    throw err;
  }
}

/**
 * Check if Strapi is reachable and responding.
 * Helpful for health checks or conditional rendering logic.
 */
export async function pingStrapi(): Promise<boolean> {
  try {
    const res = await strapiFetch<{ data: any[] }>(
      "/api/sekcje-strona-glownas?pagination[limit]=1"
    );
    return Array.isArray(res.data);
  } catch {
    return false;
  }
}

/**
 * Fetch all homepage sections sorted by `order`.
 * Used for rendering dynamic content blocks on landing pages.
 */
export async function getSections(locale?: SupportedLocale): Promise<any[]> {
  const res = await strapiFetch<{ data: any[] }>(
    "/api/sekcje-strona-glownas?populate[video][fields][0]=url&populate[image][fields][0]=url&sort=order",
    {},
    "GET",
    locale
  );
  return res.data;
}

/**
 * Fetch a single homepage section by ID.
 * Used for section preview/editing.
 */
export async function getSection(id: number | string, locale?: SupportedLocale): Promise<any> {
  const res = await strapiFetch<{ data: any }>(`/api/sekcje-strona-glownas/${id}`, {}, "GET", locale);
  return res.data;
}

export const getMediaUrl = (media?: any): string | undefined => {
  const path =
    media?.url || // bezpośredni obiekt
    media?.data?.url || // czasem tak wraca
    media?.data?.attributes?.url; // fallback

  if (!path) return undefined;

  const base = process.env.NEXT_PUBLIC_STRAPI_URL?.replace(/\/+$/, "") || "";
  return `${base}${path}`;
};

export async function getSocialLinks(locale?: SupportedLocale): Promise<any[]> {
  const res = await strapiFetch<{ data: any[] }>("/api/social-links-plural", {}, "GET", locale);
  return res.data;
}

export async function getMetaData(locale?: SupportedLocale): Promise<any[]> {
  const res = await strapiFetch<{ data: any[] | any }>(
    "/api/meta-data?populate[Logo][fields][0]=url",
    {},
    "GET",
    locale
  );

  if (Array.isArray(res.data)) return res.data;
  return res.data ? [res.data] : [];
}

/**
 * Pobiera dane z kolekcji „Kontakt edycja”
 */
export async function getContactContent(locale?: SupportedLocale): Promise<any> {
  const res = await strapiFetch<{ data: any[] }>(
    "/api/kontakt-edycjas?populate[zdjecie_sekcji][fields][0]=url",
    {},
    "GET",
    locale
  );
  return res.data?.[0]; // Zakładamy pojedynczy wpis
}

// -----------------------------------------------------------------------------
// Sorting helpers (numer_sortowania)
// -----------------------------------------------------------------------------

function parseSortNumber(value: unknown): number | null {
  if (value === null || value === undefined) return null;

  // obsłuż number / string / whitespace / przecinek
  const raw = typeof value === "number" ? value : Number(String(value).trim().replace(",", "."));
  if (!Number.isFinite(raw)) return null;

  return raw;
}

/**
 * Sortowanie:
 * - elementy z numerem idą na górę, rosnąco
 * - elementy bez numeru idą na dół
 * - jeżeli WSZYSTKIE są bez numeru -> zostaje kolejność z API (stabilnie)
 */
export function sortByNumerSortowania<T extends Record<string, any>>(
  items: T[],
  getValue: (item: T) => unknown
): T[] {
  const decorated = items.map((item, idx) => {
    const n = parseSortNumber(getValue(item));
    return { item, idx, n };
  });

  const anyHasNumber = decorated.some((d) => d.n !== null);
  if (!anyHasNumber) {
    // nigdzie nie wpisano numeru -> zachowaj "jak przyszło"
    return items;
  }

  decorated.sort((a, b) => {
    const an = a.n;
    const bn = b.n;

    const aHas = an !== null;
    const bHas = bn !== null;

    // z numerem zawsze przed bez numeru
    if (aHas && !bHas) return -1;
    if (!aHas && bHas) return 1;

    // obie bez numeru -> zachowaj kolejność wejściową (stabilnie)
    if (!aHas && !bHas) return a.idx - b.idx;

    // obie z numerem -> rosnąco, a przy remisie stabilnie
    if (an! !== bn!) return an! - bn!;
    return a.idx - b.idx;
  });

  return decorated.map((d) => d.item);
}

// -----------------------------------------------------------------------------
// Career
// -----------------------------------------------------------------------------

export async function getCareerCards(locale?: SupportedLocale): Promise<any[]> {
  const res = await strapiFetch<{ data: any[] }>(
    "/api/kariera-edycja-karts?sort=numer_sortowania:asc&populate=zdjecie_pracy",
    {},
    "GET",
    locale
  );

  const data = res.data || [];

  // Ujednolicamy dostęp do numer_sortowania (płasko lub attributes)
  const mapped = data.map((item: any) => ({
    ...item,
    numer_sortowania: item?.numer_sortowania ?? item?.attributes?.numer_sortowania ?? null,
  }));

  return sortByNumerSortowania(mapped, (it) => it.numer_sortowania);
}

export async function getCareerSection(locale?: SupportedLocale): Promise<any> {
  const res = await strapiFetch<{ data: any[] }>(
    "/api/kariera-edycja-oknas?populate[hero_image][fields][0]=url",
    {},
    "GET",
    locale
  );
  return res.data?.[0]; // zakładamy, że to singleton
}

// -----------------------------------------------------------------------------
// Offer
// -----------------------------------------------------------------------------

export async function getOfferModalSettings(locale?: SupportedLocale): Promise<any> {
  const res = await strapiFetch<{ data: any }>(
    "/api/oferta-edycja-oknas?populate=hero_image",
    {},
    "GET",
    locale
  );
  return res.data?.[0] || null;
}

export async function getOfferCards(locale?: SupportedLocale) {
  const res = await strapiFetch<{ data: any[] }>(
    "/api/oferta-edycja-karts?sort=numer_sortowania:asc&populate=video",
    {},
    "GET",
    locale
  );

  const mapped =
    res?.data?.map((item: any) => ({
      id: item.id,
      title: item.title ?? item?.attributes?.title,
      description: item.description ?? item?.attributes?.description,
      video: item.video ?? item?.attributes?.video,
      numer_sortowania: item.numer_sortowania ?? item?.attributes?.numer_sortowania ?? null,
    })) || [];

  return sortByNumerSortowania(mapped, (it) => it.numer_sortowania);
}



// -----------------------------------------------------------------------------
// Portfolio  
// -----------------------------------------------------------------------------

export async function getPortfolioModalSettings(locale?: SupportedLocale): Promise<any> {
  const res = await strapiFetch<{ data: any }>(
    "/api/portfolio-edycja-oknas?populate=hero_image",
    {},
    "GET",
    locale
  );
  return res.data?.[0] || null;
}

export async function getPortfolioCards(locale?: SupportedLocale) {
  const res = await strapiFetch<{ data: any[] }>(
    "/api/portfolio-edycja-karts?sort=numer_sortowania:asc&populate=video",
    {},
    "GET",
    locale
  );


  const mapped =
    res?.data?.map((item: any) => ({
      id: item.id,
      title: item.title ?? item?.attributes?.title,
      description: item.description ?? item?.attributes?.description,
      video: item.video ?? item?.attributes?.video,
      numer_sortowania: item.numer_sortowania ?? item?.attributes?.numer_sortowania ?? null,
    })) || [];

  return sortByNumerSortowania(mapped, (it) => it.numer_sortowania);
}