import React from "react";
import type { JoomlaArticle, WriterProfile } from "@/services/joomlaService";
import { DraftTabs } from "@/components/common/DraftTabs";
import { SamplesCarousel } from "@/components/common/SamplesCarousel";
import { ReviewsCarousel } from "@/components/common/ReviewsCarousel";
import { WhyChooseSlider } from "@/components/common/WhyChooseSlider";
import { AffiliateReviewsCarousel } from "@/components/common/AffiliateReviewsCarousel";
import { FaqAccordion } from "@/components/common/FaqAccordion";
import { ImgErrorFallback } from "@/components/common/ImgErrorFallback";
import { FreeToolExpertsList } from "@/components/common/FreeToolExpertsList";
import { WritersCarousel } from "@/components/home/WritersCarousel";
import { HomeBlogTabs } from "@/components/home/HomeBlogTabs";
import { HowItWorksSection } from "@/components/home/HowItWorksSection";
import { HomeServicesSlider } from "@/components/home/HomeServicesSlider";
import { CmsVideoLightboxHydrator } from "@/components/home/CmsVideoLightboxHydrator";
import {
  CUSTOM_BREADCRUMB_TOKEN,
  OUR_SERVICES_TOKEN,
  REVIEWS1_TOKEN,
  TOOL_PAGES,
} from "@/components/services/serviceConstants";

const WRITERS_TOKEN = "<!-- __WRITERS_CAROUSEL__ -->";
const BLOG_TOKEN = "<!-- __BLOG_TABS__ -->";
const HOW_IT_WORKS_TOKEN = "<!-- __HOW_IT_WORKS__ -->";
const SERVICES_SLIDER_TOKEN = "<!-- __SERVICES_SLIDER__ -->";

/**
 * `writer_code` (free-tool pages only, e.g. `summary-generator`'s
 * `.paraphras-experts` block) is `summary-tool.php`'s
 * `str_replace('writer_code', $writer_code, $message1)` —
 * `ContentHelper::writers_data('tools', ...)`. Replaced below with the real
 * `<FreeToolExpertsList>` component (real writer rows, same "Writers"
 * category/data every other writer listing in this app reads) instead of
 * stripped to nothing.
 *
 * Unlike the other tokens on this page, this one sits *mid-tag* in the raw
 * article HTML — `<div class="container">writer_code\n<div
 * class="hire-text">...` — so a naive `split("writer_code")` leaves the
 * first half ending in an unclosed `<div class="container">`. Browsers
 * silently heal that by keeping the div open and swallowing every sibling
 * after it (including the real content) as its children, which both broke
 * the layout (collapsed height — everything ended up mis-nested) and
 * caused a hydration mismatch (the server's raw-string output and React's
 * own idea of the tree disagree on where that div closes). This regex
 * matches the *whole* `<section class="paraphras-experts ...">...
 * </section>` block instead, so every replacement boundary lines up with
 * real tag boundaries and both halves stay independently well-formed.
 */
const WRITER_SECTION_RE =
  /<section class="paraphras-experts space50">\s*<div class="container">writer_code\s*(<div class="hire-text">[\s\S]*?<\/div>)\s*<\/div>\s*<\/section>/;

export interface ArticleRenderContext {
  article: JoomlaArticle;
  expertWriters: WriterProfile[];
  expertWriterImages: string[];
}

/**
 * `service.php`'s token splits (slider/writers/blog-tabs/how-it-works/the
 * per-tool form token/the writer_code section) are interleaved with the raw
 * CMS HTML by recursively splitting on each token and rendering a real
 * component in its place — see each token's own comment above for exactly
 * which Joomla template logic it replicates.
 */
export function renderArticleContent(rawHtml: string, ctx: ArticleRenderContext): React.ReactNode {
  const { article, expertWriters, expertWriterImages } = ctx;

  if (!rawHtml) return null;

  if (rawHtml.includes(SERVICES_SLIDER_TOKEN)) {
    const parts = rawHtml.split(SERVICES_SLIDER_TOKEN);
    return (
      <React.Fragment>
        {renderArticleContent(parts[0], ctx)}
        <HomeServicesSlider />
        {renderArticleContent(parts[1], ctx)}
      </React.Fragment>
    );
  }

  if (rawHtml.includes(WRITERS_TOKEN)) {
    const parts = rawHtml.split(WRITERS_TOKEN);
    return (
      <React.Fragment>
        {renderArticleContent(parts[0], ctx)}
        <WritersCarousel />
        {renderArticleContent(parts[1], ctx)}
      </React.Fragment>
    );
  }

  if (rawHtml.includes(HOW_IT_WORKS_TOKEN)) {
    const parts = rawHtml.split(HOW_IT_WORKS_TOKEN);
    return (
      <React.Fragment>
        {renderArticleContent(parts[0], ctx)}
        <HowItWorksSection />
        {renderArticleContent(parts[1], ctx)}
      </React.Fragment>
    );
  }

  if (rawHtml.includes(BLOG_TOKEN)) {
    const parts = rawHtml.split(BLOG_TOKEN);
    return (
      <React.Fragment>
        {renderArticleContent(parts[0], ctx)}
        <HomeBlogTabs />
        {renderArticleContent(parts[1], ctx)}
      </React.Fragment>
    );
  }

  const toolPage = TOOL_PAGES[article.alias];
  if (toolPage && rawHtml.includes(toolPage.token)) {
    const parts = rawHtml.split(toolPage.token);
    const ToolComponent = toolPage.Component;
    return (
      <React.Fragment>
        {renderArticleContent(parts[0], ctx)}
        <ToolComponent />
        {renderArticleContent(parts[1], ctx)}
      </React.Fragment>
    );
  }

  const writerSectionMatch = rawHtml.match(WRITER_SECTION_RE);
  if (writerSectionMatch) {
    const matchIndex = writerSectionMatch.index ?? rawHtml.indexOf(writerSectionMatch[0]);
    const before = rawHtml.slice(0, matchIndex);
    const after = rawHtml.slice(matchIndex + writerSectionMatch[0].length);
    const hireTextOuterHtml = writerSectionMatch[1];
    const hireTextInnerHtml = hireTextOuterHtml
      .replace(/^<div[^>]*class="hire-text"[^>]*>/i, "")
      .replace(/<\/div>\s*$/i, "");
    return (
      <React.Fragment>
        {renderArticleContent(before, ctx)}
        <section className="paraphras-experts space50">
          <div className="container">
            <FreeToolExpertsList writers={expertWriters} images={expertWriterImages} />
            <div className="hire-text" dangerouslySetInnerHTML={{ __html: hireTextInnerHtml }} />
          </div>
        </section>
        {renderArticleContent(after, ctx)}
      </React.Fragment>
    );
  }

  if (article.alias === "our-services") {
    return (
      <div
        className="our-services-content"
        dangerouslySetInnerHTML={{ __html: rawHtml }}
      />
    );
  }

  if (article.alias === "affiliate") {
    return (
      <div
        className="affiliate-page-content"
        dangerouslySetInnerHTML={{ __html: rawHtml }}
      />
    );
  }

  return (
    <div
      className="prose prose-green max-w-none text-sm text-slate-700 leading-relaxed space-y-4"
      dangerouslySetInnerHTML={{ __html: rawHtml }}
    />
  );
}

/**
 * Strips the literal placeholder tokens every Services-page (and
 * `/our-services`) CMS body carries that this app replaces with its own
 * already-rendered chrome (banner, breadcrumb) rather than leaving visible
 * as literal text — see each token's own comment in `serviceConstants.ts`.
 */
export function buildCleanHtml(articleHtml: string): string {
  return articleHtml
    .replace(OUR_SERVICES_TOKEN, "")
    .replace(CUSTOM_BREADCRUMB_TOKEN, "")
    .replace(REVIEWS1_TOKEN, "")
    .replace(/\bdata-src=/gi, "src=");
}

/** Splits the CMS article HTML at the start of the FAQ section (if present). */
export function splitArticleFaq(cleanHtml: string): { mainHtml: string; faqHtml: string | null } {
  const match = cleanHtml.match(/<(section|div)[^>]*class="[^"]*\b(faqs|faq-block|new-faq-block)\b[^"]*"/i);
  if (match && match.index !== undefined) {
    return {
      mainHtml: cleanHtml.slice(0, match.index),
      faqHtml: cleanHtml.slice(match.index),
    };
  }
  return { mainHtml: cleanHtml, faqHtml: null };
}

/** Wraps `renderArticleContent` with the real CMS-body marker checks that gate a few extra components (TOC/carousel/FAQ). */
export function renderArticleBody(cleanHtml: string, ctx: ArticleRenderContext): React.ReactNode {
  return (
    <div>
      {cleanHtml.includes("draft-tabs") && <DraftTabs />}
      {cleanHtml.includes("disertation-new-slider") && <SamplesCarousel />}
      {(cleanHtml.includes("ai-essay-reviews") || cleanHtml.includes("new_testimonials")) && <ReviewsCarousel />}
      {cleanHtml.includes("whychoose_slider") && <WhyChooseSlider />}
      {cleanHtml.includes("review_box") && <AffiliateReviewsCarousel />}
      {(cleanHtml.includes("faqs") || cleanHtml.includes("faq-head") || cleanHtml.includes("faqtop") || cleanHtml.includes("essay-dropdowns")) && <FaqAccordion />}
      {cleanHtml.includes("videopart") && <CmsVideoLightboxHydrator />}
      {/* Was gated on the `onerror="imgError"` marker alone (case 1 in
          `ImgErrorFallback`'s own comment); broadened to any `<img` at all
          now that the same component also catches images with no such
          marker that 404 because their source file isn't in this local
          Joomla mirror's media library (case 2). */}
      {cleanHtml.includes("<img") && <ImgErrorFallback />}
      {renderArticleContent(cleanHtml, ctx)}
    </div>
  );
}
