import { Metadata } from "next";
import "./article-chrome.css";
import { joomlaService, SAMPLE_LANDING_PAGES } from "@/services/joomlaService";
import { getNavigationData } from "@/app/api/navigation/route";
import { getHomePageData } from "@/app/api/home/route";
import { notFound, permanentRedirect } from "next/navigation";

import { SamplesIndexPage } from "@/components/samples/SamplesIndexPage";
import { SamplesSubjectPage } from "@/components/samples/SamplesSubjectPage";
import { SampleArticlePage } from "@/components/samples/SampleArticlePage";
import { SampleLandingPage } from "@/components/samples/SampleLandingPage";

import { QuestionsIndexPage } from "@/components/questions/QuestionsIndexPage";
import { QuestionsSubjectPage } from "@/components/questions/QuestionsSubjectPage";
import { QuestionArticlePage } from "@/components/questions/QuestionArticlePage";

import { BlogListingPage } from "@/components/blog/BlogListingPage";
import { BlogArticlePage } from "@/components/blog/BlogArticlePage";

import { WritersListingPage } from "@/components/writers/WritersListingPage";
import { WriterProfilePage } from "@/components/writers/WriterProfilePage";

import { ReviewsListingPage } from "@/components/reviews/ReviewsListingPage";

import { ServicePageView } from "@/components/services/ServicePageView";
import { GenericArticlePage } from "@/components/article/GenericArticlePage";
import { PricingPageView } from "@/components/pricing/PricingPageView";
import { OffersPageView } from "@/components/offers/OffersPageView";
import { buildCleanHtml, renderArticleBody } from "@/components/services/ArticleContentRenderer";
import { OUR_SERVICES_TOKEN, TOOL_PAGES } from "@/components/services/serviceConstants";

import { LISTING_ROUTES, resolveImageUrl, siteName } from "@/lib/pageHelpers";

interface DynamicPageProps {
  params: Promise<{
    slug: string[];
  }>;
  searchParams: Promise<{ page?: string }>;
}

export async function generateMetadata({ params }: DynamicPageProps): Promise<Metadata> {
  const resolvedParams = await params;
  const slugPath = resolvedParams.slug.join("/");

  if (slugPath === "blog") {
    return { title: `Blog | ${siteName}`, description: `Academic writing tips and guides from ${siteName}.` };
  }
  if (slugPath === "writers") {
    return { title: `Our Writers | ${siteName}`, description: `Meet the writers behind ${siteName}.` };
  }
  if (slugPath === "free-samples") {
    return { title: `Free Samples | ${siteName}`, description: `Browse free assignment samples by subject from ${siteName}.` };
  }
  if (slugPath === "reviews") {
    return { title: `Customer Reviews | ${siteName}`, description: `Real customer reviews for ${siteName}.` };
  }
  if (slugPath === "questions" || slugPath === "answers") {
    return {
      title: `Questions & Answers | ${siteName}`,
      description: `Browse expertly answered academic questions by subject from ${siteName}.`,
    };
  }

  if (resolvedParams.slug[0] === "writers" && resolvedParams.slug.length === 2) {
    const writer = await joomlaService.getWriterByAlias(resolvedParams.slug[1]);
    if (writer) {
      return { title: `${writer.name} | ${siteName}`, description: writer.bio || `Writer profile for ${writer.name}` };
    }
  }

  // Real blog, questions, answers, and free-samples links often carry section prefixes
  // (e.g. `/questions/business/{alias}` or `/free-samples/subject/{alias}`)
  // — resolve by the last segment rather than treating the full path as an alias.
  const isMultiSegmentPrefix =
    (resolvedParams.slug[0] === "blog" ||
      resolvedParams.slug[0] === "questions" ||
      resolvedParams.slug[0] === "answers" ||
      resolvedParams.slug[0] === "free-samples") &&
    resolvedParams.slug.length > 1;

  const articleSlug = isMultiSegmentPrefix
    ? resolvedParams.slug[resolvedParams.slug.length - 1]
    : slugPath;

  const article = await joomlaService.getArticleBySlug(articleSlug);

  if (!article) {
    return {
      title: `Page Not Found | ${siteName}`,
    };
  }

  /**
   * `article.metadesc` is empty for some articles (e.g. the free-tool pages
   * like `summary-generator`), whose `introtext` opens with markup
   * (`<div class="tools-navbar">...`) rather than prose — slicing the raw
   * HTML dumped that markup straight into `<meta name="description">`.
   * Stripped of tags and collapsed whitespace here so the fallback is always
   * readable text, same as every other description source. Also strips the
   * article's own literal tool-form token (e.g. `ai_humanizer_form`) if it's
   * the free-tool page that token belongs to — the same text swapped for a
   * real component in the page body, so it shouldn't show up as a stray
   * word in the meta description either.
   */
  const toolToken = TOOL_PAGES[article.alias]?.token;
  const fallbackDescription = article.introtext
    ?.replace(/<[^>]*>/g, " ")
    .replace(toolToken ? new RegExp(toolToken.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g") : /(?!)/, " ")
    .replace(/\s+/g, " ")
    .trim()
    .slice(0, 160);

  return {
    title: `${article.title} | ${siteName}`,
    description: article.metadesc || fallbackDescription || `${siteName} Service`,
    keywords: article.metakey || "assignment help, academic writing, essay writing",
  };
}

/**
 * Menu items whose live-site link points at a category view with no
 * single backing article (same class of gap as the "Samples"/"Questions"
 * category-listing problem documented in AGENTS.md §8) — the live site's
 * own `Fix404ErrorLinks` redirect table actually 301s `/assignment-subjects`
 * to `/our-services`, but this app sends it to the homepage instead, per
 * explicit product direction rather than that live redirect target.
 */
const LEGACY_ALIAS_REDIRECTS: Record<string, string> = {
  "assignment-subjects": "/",
};

export default async function DynamicJoomlaPage({ params, searchParams }: DynamicPageProps) {
  const resolvedParams = await params;
  const slugPath = resolvedParams.slug.join("/");

  if (resolvedParams.slug.length === 1 && resolvedParams.slug[0] in LEGACY_ALIAS_REDIRECTS) {
    permanentRedirect(LEGACY_ALIAS_REDIRECTS[resolvedParams.slug[0]]);
  }

  // The live site's "sample landing" pages (`/case-study-examples`,
  // `/essay-examples`, ...) — a distinct article layout keyed purely by
  // the URL alias itself (the live template's own hardcoded routing has
  // no other signal either — see `SAMPLE_LANDING_PAGES`'s comment).
  if (resolvedParams.slug.length === 1 && resolvedParams.slug[0] in SAMPLE_LANDING_PAGES) {
    return <SampleLandingPage alias={resolvedParams.slug[0]} />;
  }

  if (LISTING_ROUTES.has(slugPath)) {
    const resolvedSearchParams = await searchParams;
    const page = Math.max(1, Number(resolvedSearchParams.page) || 1);
    if (slugPath === "blog") return <BlogListingPage page={page} />;
    if (slugPath === "writers") return <WritersListingPage page={page} />;
    if (slugPath === "reviews") return <ReviewsListingPage page={page} />;
    if (slugPath === "questions") return <QuestionsIndexPage basePath="/questions" />;
    if (slugPath === "answers") return <SamplesIndexPage basePath="/answers" />;
    return <SamplesIndexPage basePath="/free-samples" />;
  }

  if (
    (resolvedParams.slug[0] === "free-samples" || resolvedParams.slug[0] === "answers") &&
    resolvedParams.slug.length === 2
  ) {
    const resolvedSearchParams = await searchParams;
    const page = Math.max(1, Number(resolvedSearchParams.page) || 1);
    return (
      <SamplesSubjectPage
        subjectAlias={resolvedParams.slug[1]}
        page={page}
        basePath={`/${resolvedParams.slug[0]}`}
      />
    );
  }

  if (resolvedParams.slug[0] === "questions" && resolvedParams.slug.length === 2) {
    const resolvedSearchParams = await searchParams;
    const page = Math.max(1, Number(resolvedSearchParams.page) || 1);
    return (
      <QuestionsSubjectPage
        subjectAlias={resolvedParams.slug[1]}
        page={page}
        basePath="/questions"
      />
    );
  }

  if (resolvedParams.slug[0] === "questions" && resolvedParams.slug.length === 3) {
    return (
      <QuestionArticlePage
        subjectAlias={resolvedParams.slug[1]}
        alias={resolvedParams.slug[2]}
        basePath="/questions"
      />
    );
  }

  if (
    (resolvedParams.slug[0] === "free-samples" || resolvedParams.slug[0] === "answers") &&
    resolvedParams.slug.length === 3
  ) {
    return (
      <SampleArticlePage
        subjectAlias={resolvedParams.slug[1]}
        alias={resolvedParams.slug[2]}
        basePath={`/${resolvedParams.slug[0]}`}
      />
    );
  }

  if (resolvedParams.slug[0] === "writers" && resolvedParams.slug.length === 2) {
    return <WriterProfilePage alias={resolvedParams.slug[1]} />;
  }

  // Real blog, questions, answers, and free-samples links often carry section prefixes
  // (e.g. `/questions/business/{alias}` or `/answers/business/{alias}`)
  // — resolve by the last segment rather than treating the full path as an alias.
  const articleSlug =
    (resolvedParams.slug[0] === "blog" ||
      resolvedParams.slug[0] === "questions" ||
      resolvedParams.slug[0] === "answers" ||
      resolvedParams.slug[0] === "free-samples") &&
      resolvedParams.slug.length > 1
      ? resolvedParams.slug[resolvedParams.slug.length - 1]
      : slugPath;

  // A single blog post gets its own real layout (sidebar calculator, free
  // tools, latest posts — see `BlogArticlePage`), not the generic
  // breadcrumb+card wrapper every other article type falls through to below.
  if (resolvedParams.slug[0] === "blog" && resolvedParams.slug.length > 1) {
    return <BlogArticlePage alias={articleSlug} />;
  }

  const [article, navigationData, orderConfig, bestDeals, pricing] = await Promise.all([
    joomlaService.getArticleBySlug(articleSlug),
    getNavigationData(),
    joomlaService.getOrderServiceConfig(),
    joomlaService.getBestDeals(),
    joomlaService.getPricingConfig(),
  ]);

  // Needs the article id/alias, so it can't join the Promise.all above.
  // Only fetched for the one free-tool page that actually renders it.
  const expertWriters =
    article?.alias === "summary-generator" ? (await joomlaService.getWriters(4, 0)).data : [];
  const expertWriterImages = await Promise.all(expertWriters.map((w) => resolveImageUrl(w.imageUrl)));

  // STRICT RULE: If no article is found in Joomla DB / API, return 404 Error page immediately.
  // Do NOT navigate to live external website or display fallback placeholder.
  // `/offers` is a real, published article (id 25) whose CMS body is
  // genuinely empty — it renders entirely through `offers.php`'s own
  // template (coupon cards from the central `coupons` table, seasonal
  // banner from `crm_offers`), same as `/affiliate`'s dedicated layout —
  // so an empty `introtext`/`fulltext` there isn't a missing article.
  if (!article || (articleSlug !== "offers" && !article.introtext && !article.fulltext)) {
    notFound();
  }

  /**
   * A bare/non-prefixed alias (no `/free-samples/...` or `/questions/...`
   * segment) for an article that actually lives under one of those real
   * subtrees. The live site 301-redirects these to the canonical prefixed
   * URL (confirmed: `/acc20007-...` → `/answers/accounting/acc20007-...`,
   * paywall active there) rather than rendering content at the bare URL.
   */
  const isBareAlias =
    resolvedParams.slug.length === 1 &&
    resolvedParams.slug[0] !== "free-samples" &&
    resolvedParams.slug[0] !== "questions" &&
    resolvedParams.slug[0] !== "answers" &&
    resolvedParams.slug[0] !== "blog";

  if (isBareAlias) {
    const location = await joomlaService.getArticleLocation(article.alias);
    if (location.rootType === "samples" && location.subjectAlias) {
      permanentRedirect(`/free-samples/${location.subjectAlias}/${article.alias}`);
    }
    if (location.rootType === "questions" && location.subjectAlias) {
      permanentRedirect(`/answers/${location.subjectAlias}/${article.alias}`);
    }
  }

  if (resolvedParams.slug[0] === "free-samples" || article.pageType === "Samples" || article.university) {
    const subjectAlias =
      resolvedParams.slug.length >= 2 && resolvedParams.slug[0] === "free-samples"
        ? resolvedParams.slug[1]
        : "business-assignment-help";
    return <SampleArticlePage subjectAlias={subjectAlias} alias={article.alias} />;
  }

  if (article.pageType === "Questions" || article.questionHtml) {
    const rootPrefix =
      resolvedParams.slug[0] === "questions" || resolvedParams.slug[0] === "answers"
        ? resolvedParams.slug[0]
        : "answers";
    const subjectAlias =
      (resolvedParams.slug[0] === "questions" || resolvedParams.slug[0] === "answers") &&
      resolvedParams.slug.length >= 2
        ? resolvedParams.slug[1]
        : "business";
    return (
      <QuestionArticlePage
        subjectAlias={subjectAlias}
        alias={article.alias}
        basePath={`/${rootPrefix}`}
      />
    );
  }

  /**
   * Some CMS articles (`summary-generator` among them) store their `text`
   * field with literal `\r\n` line endings. The browser's HTML parser
   * normalizes those to `\n` in text nodes, but React's hydration check
   * compares against the original (CRLF-containing) string, so any article
   * with them fails to hydrate on first paint — normalizing here keeps the
   * two in sync instead of leaving it to React's recovery-by-full-rerender.
   */
  const articleHtml = [article.introtext, article.fulltext]
    .filter(Boolean)
    .join("\n")
    .replace(/\r\n/g, "\n");

  const hasOurServicesBanner = articleHtml.includes(OUR_SERVICES_TOKEN);
  const isServicesPage = article.isServicePage || hasOurServicesBanner;
  const cleanHtml = buildCleanHtml(articleHtml);

  const calculatorConfig = isServicesPage ? (await getHomePageData()).hero.calculator : null;

  if (isServicesPage && calculatorConfig) {
    return (
      <ServicePageView
        article={article}
        navigationData={navigationData}
        orderConfig={orderConfig}
        bestDeals={bestDeals}
        pricing={pricing}
        calculatorConfig={calculatorConfig}
        hasOurServicesBanner={hasOurServicesBanner}
        cleanHtml={cleanHtml}
        expertWriters={expertWriters}
        expertWriterImages={expertWriterImages}
      />
    );
  }

  const articleBody = renderArticleBody(cleanHtml, { article, expertWriters, expertWriterImages });

  /**
   * `/tools` ("Free Resources" → "Tools" on the live site) has no
   * `page-layout` field, so it isn't a Services page. Its CMS body isn't
   * just a banner blurb, though — it's the *entire* page: the USP badge
   * strip (`.variety-tools`/`.variety-usp`) and the flip-card tool grid
   * (`.online-tools`/`.card`/`.inner-div`) are both real article content,
   * styled by `app/tools-page.css` (the flip itself is a pure `:hover`
   * rule there, no JS needed).
   */
  if (articleSlug === "tools") {
    return <div className="bg-white">{articleBody}</div>;
  }

  /**
   * Every other free-tool page in `TOOL_PAGES`, like `/summary-generator`
   * and `/tools`, has no `page-layout` field but its CMS body is the entire
   * real page (tools nav, banner, its own form token swapped for the real
   * tool component above, benefits, FAQ) — styled by `app/summary-tool.css`
   * (shared chrome: `.tools-navbar`, `.description`, `.faq-block`, etc. —
   * see that file's header), not the generic breadcrumb+card wrapper below.
   */
  if (articleSlug in TOOL_PAGES) {
    return <div className="bg-white">{articleBody}</div>;
  }

  /**
   * `/affiliate` renders through its own dedicated layout (`affiliate.php`
   * + `become-partner.css` / `app/css/affiliate.css`), containing its own
   * full-bleed hero banner, calculator, invite tools, and reviews — not
   * the generic breadcrumb+card wrapper.
   */
  if (articleSlug === "affiliate") {
    return <div className="bg-white">{articleBody}</div>;
  }

  /**
   * `/offers` has no CMS article body at all (see the `notFound()` guard
   * above) — it renders entirely through `offers.php` + `offers.css`
   * (`app/css/offers.css`): real coupon cards from the central `coupons`
   * table and a seasonal banner/strip from `crm_offers`, both live per
   * request, not hardcoded.
   */
  if (articleSlug === "offers") {
    const [offers, offerEvent] = await Promise.all([
      joomlaService.getAllOffers(),
      joomlaService.getOfferEvent(),
    ]);
    return (
      <OffersPageView
        article={article}
        navigationData={navigationData}
        offers={offers}
        offerEvent={offerEvent}
      />
    );
  }

  /**
   * `/pricing` renders through its own dedicated layout (`pricing.php` +
   * `price.css`), with hero perks + price calculator, trusted rating strip,
   * free goodies box, secure payment methods, reviews slider, and FAQ accordion.
   */
  if (articleSlug === "pricing") {
    const [reviews, homeData] = await Promise.all([
      joomlaService.getServiceReviews("pricing.php"),
      getHomePageData(),
    ]);
    return (
      <PricingPageView
        article={article}
        pricingConfig={pricing}
        calculatorConfig={homeData.hero.calculator}
        reviews={reviews}
      />
    );
  }

  return <GenericArticlePage article={article} navigationData={navigationData} articleBody={articleBody} />;
}
