type MediaSize = "small" | "medium" | "large" | "og";

const CMS_BASE_URL =
  process.env.NEXT_PUBLIC_CMS_BASE_URL || "http://localhost:3003";

export function transformCMSPage(payload: any) {
  const mapped = (payload?.layout || [])
    .map((block: any) => {
      try {
        return mapBlock(block, payload);
      } catch (e) {
        console.error("[transform] mapBlock failed:", block?.type, e);
        return null;
      }
    })
    .filter(Boolean);

  const floating = buildFloatingButtonBlock(payload, mapped);
  const footer = buildFooterBlock(payload);

  const layout = [...mapped];
  if (floating) layout.push(floating);
  if (footer) layout.push(footer);

  const cleanedMeta = payload?.meta ? { ...payload.meta } : {};
  if (cleanedMeta && typeof cleanedMeta === "object") {
    delete cleanedMeta.snippets;
  }

  const snippets = {
    ...(payload?.snippets || {}),
    ...(payload?.meta?.snippets || {}),
    ...(payload?.page?.snippets || {}),
    ...(payload?.included?.snippets || {}),
  };

  return { layout, meta: cleanedMeta, snippets };
}

function mapBlock(block: any, payload: any) {
  switch (block?.type) {
    case "heroOfferV1": {
      const headline = block?.props?.headline ?? "";
      const [leftRaw = "", rightRaw = ""] = headline.split(" - ");

      const left = leftRaw.trim();
      const right = rightRaw.trim();

      let headline1 = left;
      let headline2 = "";

      if (right) {
        const words = right.split(" ").filter(Boolean);

        if (words.length > 1) {
          const mid = Math.ceil(words.length / 2);
          const firstHalf = words.slice(0, mid).join(" ");
          const secondHalf = words.slice(mid).join(" ");

          headline1 = `${left} ${firstHalf}`.trim();
          headline2 = secondHalf.trim();
        } else {
          headline1 = `${left} ${right}`.trim();
        }
      }

      const globals =
        payload?.included?.globals ||
        payload?.globals ||
        payload?.page?.globals;

      const logoId = globals?.header?.logo;
      const bgId = block?.props?.backgroundImageId;

      const logo =
        media(payload, logoId, "small") ||
        media(payload, logoId, "medium") ||
        media(payload, logoId);

      const bg =
        media(payload, bgId, "large") ||
        media(payload, bgId, "og") ||
        media(payload, bgId, "medium") ||
        media(payload, bgId, "small") ||
        media(payload, bgId);

      return {
        blockType: "hero",
        logoHref: "/",
        logoSrc: abs(logo) ?? null,
        logoAlt: "Logo",
        heroImageLandscape: abs(bg) ?? null,
        heroImagePortrait: null,
        headline1,
        headline2,
        ctaLabel:
          block?.props?.primaryCTA?.label ??
          globals?.header?.landingCTA?.label ??
          "Send Request",
        ctaHref:
          block?.props?.primaryCTA?.href ??
          globals?.header?.landingCTA?.href ??
          "#send-request",
        ctaId:
          block?.props?.ctas?.[0]?.ctaId ??
          globals?.header?.landingCTA?.ctaId ??
          null,
        promoItems: (block?.props?.highlights || []).map((h: any) => {
          const rawLabel = String(h?.label ?? "").trim();
          const words = rawLabel.split(/\s+/).filter(Boolean);

          let title = rawLabel;
          let subtitle = "";

          if (words.length > 1) {
            title = words.slice(0, -1).join(" ");
            subtitle = words.slice(-1).join(" ");
          }

          return {
            iconSrc: abs(media(payload, h?.iconId, "small")) ?? null,
            title,
            subtitle,
          };
        }),
      };
    }

    case "richTextV1": {
      const root = block?.props?.content?.root;
      const children = root?.children || [];

      const headingNode = children.find((n: any) => n?.type === "heading");
      const headingText = extractPlainText(headingNode) || "";

      const paragraphs = children
        .filter((n: any) => n?.type === "paragraph")
        .map((p: any) => paragraphToHtml(p, payload))
        .map((html: string) => html.trim())
        .filter((html: string) => html.length > 0);

      const headingLower = headingText.toLowerCase();

      if (headingLower.includes("ready to get scilly")) {
        const globals =
          payload?.included?.globals ||
          payload?.globals ||
          payload?.page?.globals;

        return {
          blockType: "cards",
          titleBlock: { icon: null, heading: "", subText: "" },
          packages: [],
          inclusionsTitle: { icon: null, heading: "" },
          inclusions: [],
          expectTitle: { icon: null, heading: "" },
          expectItems: [],
          cta: {
            headline: headingText,
            paragraphs,
            buttonLabel: globals?.header?.landingCTA?.label ?? "Send Request",
            buttonHref: globals?.header?.landingCTA?.href ?? "#send-request",
          },
        };
      }

      return {
        blockType: "introText",
        heading: headingText || undefined,
        paragraphs: paragraphs.length ? paragraphs : undefined,
      };
    }

    case "contentListV1": {
  const heading = String(block?.props?.heading ?? "").trim();
  const headingLower = heading.toLowerCase();
  const items = Array.isArray(block?.props?.items) ? block.props.items : [];
  const intro = String(block?.props?.intro ?? "").trim();

  const firstIcon =
    abs(media(payload, block?.props?.ornamentId, "small")) ||
    abs(media(payload, items?.[0]?.iconId, "small")) ||
    null;

  const emptyCardsBlock = {
    blockType: "cards",
    titleBlock: { icon: null, heading: "", subText: "" },
    packages: [],
    inclusionsTitle: { icon: null, heading: "" },
    inclusions: [],
    expectTitle: { icon: null, heading: "" },
    expectItems: [],
    cta: null,
  };

  if (
    headingLower.includes("include") ||
    headingLower.includes("included") ||
    headingLower.includes("inclusion") ||
    headingLower.includes("what's included") ||
    headingLower.includes("whats included")
  ) {
    const inclusions = items.map((it: any) => ({
      title: it?.title ?? "",
      description: it?.body
        ? bodyToHtml(it.body?.root ?? it.body, payload)
        : "",
      image:
        abs(media(payload, it?.imageId, "large")) ??
        abs(media(payload, it?.imageId, "small")) ??
        null,
      icon: abs(media(payload, it?.iconId, "small")) ?? null,
    }));

    return {
      ...emptyCardsBlock,
      inclusionsTitle: {
        icon: firstIcon,
        heading,
      },
      inclusions,
    };
  }


  if (
    headingLower.includes("expect") ||
    headingLower.includes("what to expect")
  ) {
    const expectItems = items.map((it: any) => ({
      title: it?.title ?? "",
      description: it?.body
        ? bodyToHtml(it.body?.root ?? it.body, payload)
        : "",
      image:
        abs(media(payload, it?.imageId, "large")) ??
        abs(media(payload, it?.imageId, "small")) ??
        null,
      icon: abs(media(payload, it?.iconId, "small")) ?? null,
    }));

    return {
      ...emptyCardsBlock,
      expectTitle: {
        icon: firstIcon,
        heading,
      },
      expectItems,
    };
  }

  if (
    headingLower.includes("package") ||
    headingLower.includes("packages") ||
    headingLower.includes("offer") ||
    headingLower.includes("offers") ||
    headingLower.includes("stay") ||
    headingLower.includes("stays")
  ) {
    const packages = items.map((it: any) => ({
      title: it?.title ?? "",
      nights: it?.eyebrow ?? "",
      price: it?.priceLine ?? "",
      subtitle: it?.subline ?? "",
      description: it?.body
        ? bodyToHtml(it.body?.root ?? it.body, payload)
        : "",
      image:
        abs(media(payload, it?.imageId, "large")) ??
        abs(media(payload, it?.imageId, "small")) ??
        null,
      icon: abs(media(payload, it?.iconId, "small")) ?? null,
    }));

    return {
      ...emptyCardsBlock,
      titleBlock: {
        icon: firstIcon,
        heading,
        subText: intro,
      },
      packages,
    };
  }

  return {
    blockType: "contentList",
    heading,
    intro,
    icon: firstIcon,
    items: items.map((it: any) => ({
      title: it?.title ?? "",
      description: it?.body
        ? bodyToHtml(it.body?.root ?? it.body, payload)
        : "",
      image:
        abs(media(payload, it?.imageId, "large")) ??
        abs(media(payload, it?.imageId, "small")) ??
        null,
      icon: abs(media(payload, it?.iconId, "small")) ?? null,
    })),
  };
}

    case "leadFormV1": {
      const globals =
        payload?.included?.globals ||
        payload?.globals ||
        payload?.page?.globals;

      const formId = block?.props?.formId;

      const form =
        (formId != null ? payload?.included?.forms?.[String(formId)] : null) ||
        payload?.included?.forms?.["1"] ||
        null;

      if (!form) {
        console.warn("[transform] leadFormV1: form not found", {
          formId,
          availableFormIds: Object.keys(payload?.included?.forms || {}),
        });

        return {
          blockType: "requestForm",
          title: block?.props?.heading || "Send Request Form",
          fields: {
            firstName: { label: "FIRST NAME", required: true },
            lastName: { label: "LAST NAME", required: true },
            email: { label: "EMAIL ADDRESS", required: true },
            phone: { label: "MOBILE NUMBER", required: false, country: "in" },
            package: { label: "CHOOSE PACKAGE", required: true },
            bestTime: { label: "BEST TIME TO CONTACT", required: true },
          },
          packages: [],
          terms: {
            id: "terms",
            text: "I authorize Karma Group to contact me.",
            required: true,
          },
          submit: {
            label: globals?.header?.landingCTA?.label || "SUBMIT REQUEST NOW",
            id: null,
          },
          redirect: undefined,
          ui: {
            containerMaxWidth: 1140,
            inputHeightPx: 49.7,
            borderColor: "#555555",
            borderWidthPx: 2.5,
            fontFamily: "Montserrat",
          },
          formId: formId ?? null,
        };
      }

      const cmsFields = Array.isArray(form?.fields) ? form.fields : [];

      const findField = (type: string, contains: string) =>
        cmsFields.find((f: any) => {
          const hay = `${f?.name || ""} ${f?.label || ""}`.toUpperCase();
          return f?.blockType === type && hay.includes(contains.toUpperCase());
        });

      const firstName =
        findField("text", "FIRST NAME") || findField("text", "FIRST");
      const lastName =
        findField("text", "LAST NAME") || findField("text", "LAST");
      const email = findField("email", "EMAIL");

      const phone =
        findField("phone", "MOBILE") ||
        findField("phone", "PHONE") ||
        cmsFields.find((f: any) => f?.blockType === "phone");

      const pkg =
        findField("select", "CHOOSE PACKAGE") ||
        findField("select", "PACKAGE") ||
        findField("select", "CHOOSE") ||
        cmsFields.find((f: any) => f?.blockType === "select");

      const bestTime =
        findField("text", "BEST TIME") || findField("text", "CONTACT");

      const terms =
        findField("checkbox", "AUTHORIZE") ||
        findField("checkbox", "TERMS") ||
        cmsFields.find((f: any) => f?.blockType === "checkbox");

      const packages = (pkg?.options || [])
        .filter((o: any) => o?.value && o?.value !== pkg?.defaultValue)
        .map((o: any) => ({ title: o.value }));

      return {
        blockType: "requestForm",
        title: form?.title || block?.props?.heading || "Send Request Form",
        fields: {
          firstName: {
            label: firstName?.label || "FIRST NAME",
            required: firstName?.required ?? true,
          },
          lastName: {
            label: lastName?.label || "LAST NAME",
            required: lastName?.required ?? true,
          },
          email: {
            label: email?.label || "EMAIL ADDRESS",
            required: email?.required ?? true,
          },
          phone: {
            label: phone?.label || "MOBILE NUMBER",
            required: phone?.required ?? false,
            country: (phone?.defaultCountry || "IN").toLowerCase(),
          },
          package: {
            label: pkg?.label || "CHOOSE PACKAGE",
            required: pkg?.required ?? true,
          },
          bestTime: {
            label: bestTime?.label || "BEST TIME TO CONTACT",
            required: bestTime?.required ?? true,
          },
        },
        packages,
        terms: {
          id: terms?.id || "terms",
          text: terms?.label || "I authorize Karma Group to contact me.",
          required: terms?.required ?? true,
        },
        submit: {
          label:
            form?.submitButtonLabel ||
            globals?.header?.landingCTA?.label ||
            "SUBMIT REQUEST NOW",
          id: form?.submitButtonId ?? null,
        },
        redirect: form?.redirect
          ? {
              redirectType: form.redirect?.redirectType,
              url: form.redirect?.url,
              slug: form.redirect?.slug,
              openInNewTab: form.redirect?.openInNewTab ?? false,
              head: form.redirect?.head,
              bodyTop: form.redirect?.bodyTop,
              bodyBottom: form.redirect?.bodyBottom,
            }
          : undefined,
        ui: {
          containerMaxWidth: 1140,
          inputHeightPx: 49.7,
          borderColor: "#555555",
          borderWidthPx: 2.5,
          fontFamily: "Montserrat",
        },
        formId: formId ?? form?.id ?? null,
      };
    }

    case "imageGalleryStripV1": {
      const rawImages = Array.isArray(block?.props?.images)
        ? block.props.images
        : [];

      const imgs = rawImages
        .map((img: any) => {
          const id = img?.imageId ?? img?.id ?? img?.mediaId ?? img?.uploadId;
          if (id == null) return null;

          const m =
            payload?.included?.media?.[String(id)] ||
            payload?.included?.media?.[id];

          const url =
            abs(m?.sizes?.small?.url) ||
            abs(m?.sizes?.medium?.url) ||
            abs(m?.url) ||
            null;

          if (!url) return null;

          return {
            id,
            url,
            alt: img?.alt || m?.alt || "",
          };
        })
        .filter(Boolean);

      if (imgs.length === 0) return null;

      return { blockType: "carousel", images: imgs };
    }

    default:
      return null;
  }
}

function buildFloatingButtonBlock(payload: any, mappedLayout: any[]) {
  const globals =
    payload?.included?.globals || payload?.globals || payload?.page?.globals;

  const globalCTA = globals?.header?.landingCTA;
  const hero = mappedLayout.find((b: any) => b?.blockType === "hero");

  const label = String(
    globalCTA?.label || hero?.ctaLabel || "Send Request",
  ).toUpperCase();

  const href = globalCTA?.href || hero?.ctaHref || "#send-request";
  if (!href) return null;

  const ctaId = globalCTA?.ctaId || hero?.ctaId || null;

  return {
    blockType: "floatingButton",
    label,
    href,
    icon: "chevronRight",
    ctaId,
  };
}

function buildFooterBlock(payload: any) {
  const globals =
    payload?.included?.globals || payload?.globals || payload?.page?.globals;

  const footer = globals?.footer;
  const text = footer?.copyright || footer?.text || footer?.label || null;
  if (!text) return null;

  return {
    blockType: "footer",
    text,
    variant: footer?.variant || "default",
  };
}

function media(payload: any, id?: number, size: MediaSize = "small") {
  if (!id) return null;
  const m =
    payload?.included?.media?.[String(id)] || payload?.included?.media?.[id];
  return m?.sizes?.[size]?.url || m?.url || null;
}

function abs(path?: string | null) {
  if (!path) return null;

  let url = path.startsWith("http") ? path : `${CMS_BASE_URL}${path}`;

  if (
    url.startsWith("https://storage.googleapis.com/test-csm-ptichbook/") &&
    !url.includes("/karmapitchbookimages/")
  ) {
    url = url.replace(
      "https://storage.googleapis.com/test-csm-ptichbook/",
      "https://storage.googleapis.com/test-csm-ptichbook/karmapitchbookimages/",
    );
  }

  return url;
}

function extractPlainText(node: any): string {
  if (!node) return "";
  const children = node?.children || [];
  let out = "";

  for (const c of children) {
    if (c?.type === "text") out += c?.text ?? "";
    else if (c?.type === "linebreak") out += "\n";
    else if (c?.children) out += extractPlainText(c);
  }

  return out.trim();
}

function bodyToHtml(node: any, payload: any): string {
  if (!node) return "";
  const children = node?.children || [];
  let html = "";

  for (const p of children) {
    if (p?.type === "paragraph") {
      html += paragraphToHtml(p, payload) + "<br/>";
    }
  }

  return html.trim();
}

function paragraphToHtml(p: any, payload: any): string {
  const children = p?.children || [];
  let html = "";

  for (const c of children) {
    if (c?.type === "text") html += formatTextSpan(c);
    else if (c?.type === "linebreak") html += "<br/>";
    else if (
      c?.type === "image" ||
      c?.type === "upload" ||
      c?.type === "inlineImage"
    ) {
      const id = c?.id || c?.imageId || c?.mediaId;
      const src =
        abs(media(payload, id, "large")) || abs(media(payload, id, "small"));

      if (src) {
        html += `<img src="${src}" alt="" loading="lazy" decoding="async" style="max-width:100%;height:auto;" />`;
      }
    }
  }

  return html;
}

function formatTextSpan(t: any): string {
  const text = escapeHtml(t?.text ?? "");
  const format = t?.format ?? 0;

  let out = text;
  if (format & 1) out = `<strong>${out}</strong>`;
  if (format & 2) out = `<em>${out}</em>`;
  if (format & 4) out = `<u>${out}</u>`;
  if (format & 8) out = `<s>${out}</s>`;
  return out;
}

function escapeHtml(str: string) {
  return str
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}
