import { Fragment } from "react";
import { PageContentRenderer, hasVisibleContent } from "@/components/blocks";
import type { RenderContext } from "@/components/blocks";
import { PopupHost } from "./popup-host";
import { FramedPage } from "./site-frame";
import type { PageContent } from "@/lib/blocks/layout";
import { messagesForSite } from "@/lib/services/org-translations";
import { LAYOUT_BLOCKS, type LayoutOrder } from "@/lib/site-settings";
import type { PanelPosition, PublicPage, PublicSite } from "@/lib/public/site";

type Panels = Record<PanelPosition, { id: string; content: PageContent }[]> & { above: { id: string; key: string; content: PageContent }[]; below: { id: string; key: string; content: PageContent }[] };

const FRAME_ZONES = new Set<string>(["header", "hero", "footer"]);

/**
 * Shared by the live site and the draft preview: panels around the page content, in a fixed order.
 * `frame` = the website, when its theme uses "panelFrame": the Header, Hero and Footer panels then go to the theme frame (FramedPage)
 * and the rest of the layout order renders inside <main>.
 */
export async function PageView({ page, panels, ctx, ignoreWindows = false, order, frame = null }: { order?: LayoutOrder; page: Pick<PublicPage, "title" | "content" | "showTitle" | "layout">; panels: Panels; ctx: RenderContext; ignoreWindows?: boolean; frame?: PublicSite | null }) {
  const text = panels.popup.length ? await messagesForSite(ctx.siteId) : null;
  const render = (content: PageContent) => <PageContentRenderer content={content} ctx={ctx} ignoreWindows={ignoreWindows} />;
  const showTitle = (page.showTitle && page.layout !== "homepage") || (!hasVisibleContent(page.content) && panels.header.length + panels.hero.length + panels.above.length + panels.below.length === 0);
  const headerPanels = panels.header.map((p) => <div key={p.id} data-panel="header">{render(p.content)}</div>);
  const heroPanels = panels.hero.map((p) => <div key={p.id} data-panel="hero">{render(p.content)}</div>);
  const footerPanels = panels.footer.map((p) => <div key={p.id} data-panel="footer">{render(p.content)}</div>);
  const parts: Record<(typeof LAYOUT_BLOCKS)[number], React.ReactNode> = {
    header: headerPanels,
    hero: heroPanels,
    title: showTitle ? <h1 className="site-heading site-page-title mx-auto max-w-6xl px-4 text-3xl font-bold sm:px-6">{page.title}</h1> : null,
    above: panels.above.map((p) => <div key={p.id} data-panel={p.key}>{render(p.content)}</div>),
    content: <div className={page.layout === "narrow" ? "mx-auto w-full max-w-3xl" : undefined}>{render(page.content)}</div>,
    below: panels.below.map((p) => <div key={p.id} data-panel={p.key}>{render(p.content)}</div>),
    footer: footerPanels,
  };
  const sequence = order ? (order[page.layout as keyof LayoutOrder] ?? order.default) : LAYOUT_BLOCKS;
  const popups = panels.popup.map((p) => <PopupHost key={p.id} id={p.id} label={text?.["popups.notice"] ?? "Notice"} closeLabel={text?.["popups.close"] ?? "Close"}>{render(p.content)}</PopupHost>);
  if (frame) {
    return (
      <FramedPage site={frame} header={headerPanels} hero={heroPanels} footer={footerPanels}>
        {sequence.filter((k) => !FRAME_ZONES.has(k)).map((k) => <Fragment key={k}>{parts[k]}</Fragment>)}
        {popups}
      </FramedPage>
    );
  }
  return (
    <>
      {sequence.map((k) => <Fragment key={k}>{parts[k]}</Fragment>)}
      {popups}
    </>
  );
}
