<script lang="ts">
  import '../app.css';
  import '$lib/iconify-offline';
  import { page } from '$app/stores';
  import Header from '$lib/components/Header.svelte';
  import HeaderOverlay from '$lib/components/HeaderOverlay.svelte';
  import Footer from '$lib/components/Footer.svelte';
  import TopBanner from '$lib/components/TopBanner.svelte';
  import AnnouncementBanner from '$lib/components/AnnouncementBanner.svelte';
  import DeadlineBannerBlock from '$lib/components/blocks/DeadlineBannerBlock.svelte';
  import TranslationProvider from '$lib/components/TranslationProvider.svelte';
  import ContentModal from '$lib/components/ContentModal.svelte';
  import Breadcrumbs from '$lib/ui/Breadcrumbs.svelte';
  import type { LayoutData } from './$types';
  import { ensureTransformedImage } from '$lib/rusty-image';
  import { DEFAULT_SOCIAL_IMAGE_URL, SOCIAL_IMAGE_DIMENSIONS } from '$lib/constants';
  import { onMount } from 'svelte';
  import { invalidateAll } from '$app/navigation';

  let { data, children }: { data: LayoutData; children: import('svelte').Snippet } = $props();

  /**
   * Embed-Routen (z.B. /widget/...) liegen in der `(embed)`-Route-Group und
   * sollen ohne Site-Chrome (Header, Footer, TopBanner, Breadcrumbs, Skip-Link,
   * Preview-Banner) gerendert werden — auch SEO-Tags ausser noindex sind irrelevant,
   * weil das Widget per `<iframe>` eingebettet wird.
   */
  const isEmbed = $derived(($page.route.id ?? '').startsWith('/(embed)'));

  // Nur EIN Balken über der Navi: aktive Frist hat Vorrang, sonst NEU-Banner.
  const deadlineActive = $derived.by(() => {
    const b = data.deadlineBanner as { mode?: string; date?: string; items?: unknown[] } | null;
    if (!b) return false;
    if (b.mode === 'auto') return (b.items ?? []).length > 0;
    if (!b.date) return false;
    const d = new Date(b.date);
    if (Number.isNaN(d.getTime())) return false;
    const today = new Date(); today.setHours(0, 0, 0, 0);
    const t = new Date(d); t.setHours(0, 0, 0, 0);
    return t.getTime() >= today.getTime();
  });

  // Live-preview reload bridge: when the page was loaded with
  // `?preview_draft=...`, accept `rustycms:reload` postMessage events from the
  // admin iframe parent and re-run the SvelteKit `load()` so the iframe
  // reflects the latest in-memory draft. We re-run instead of `location.reload()`
  // to keep scroll position and avoid the full document re-mount cost.
  onMount(() => {
    if (typeof window === 'undefined') return;
    const isPreviewDraft = window.location.search.includes('preview_draft=');
    if (!isPreviewDraft) return;
    const allowed = (import.meta.env.PUBLIC_PREVIEW_PARENT_ORIGIN ?? '').toString().trim();
    const handler = (event: MessageEvent) => {
      if (allowed && event.origin !== allowed) return;
      const data = event.data;
      if (!data) return;
      if (data === 'rustycms:reload' || (typeof data === 'object' && data.type === 'rustycms:reload')) {
        void invalidateAll();
      }
    };
    window.addEventListener('message', handler);
    return () => window.removeEventListener('message', handler);
  });

  // Per-page SEO data from $page.data
  const pageData = $derived($page.data as {
    seoTitle?: string;
    seoDescription?: string;
    socialImage?: string;
    ogType?: string;
    ogImageAlt?: string;
    articlePublishedTime?: string | null;
    articleModifiedTime?: string | null;
    articleAuthor?: string | null;
    articleTags?: string[];
    twitterLabel1?: string;
    twitterData1?: string;
    robots?: string;
    keywords?: string;
    preview?: boolean;
    previewDraft?: boolean;
    jsonLd?: Record<string, unknown> | Record<string, unknown>[];
    breadcrumbItems?: { href?: string; label: string }[];
    topBanner?: {
      banner: unknown;
      resolvedImages: string[];
      headline?: string;
      subheadline?: string;
      responsive?: {
        sources: { type: string; srcset: string; media?: string }[];
        fallback: string;
        width: number;
        height: number;
        lqip?: string;
      } | null;
      focalCss?: string | null;
    } | null;
  });

  const baseUrl = $derived(data.siteBaseUrl ?? '');
  const canonical = $derived(`${baseUrl}${$page.url.pathname}`);

  function applyTemplate(tpl: string | null | undefined, value: string): string {
    if (!tpl) return value;
    return tpl.replace(/\$1/g, value);
  }

  const rawSeoTitle = $derived(pageData?.seoTitle ?? data.siteName);
  const rawSeoDescription = $derived(pageData?.seoDescription ?? '');
  const seoTitle = $derived(applyTemplate(data.seoTitleTemplate, rawSeoTitle));
  const seoDescription = $derived(applyTemplate(data.seoDescriptionTemplate, rawSeoDescription));

  const socialImageUrl = $derived.by(() => {
    const raw = pageData?.socialImage ?? data.logoSocialImage ?? data.logoUrl ?? DEFAULT_SOCIAL_IMAGE_URL;
    if (!raw) return '';
    if (raw.startsWith('//')) return `https:${raw}`;
    if (raw.startsWith('http://') || raw.startsWith('https://')) return raw;
    if (raw.startsWith('/')) return `${baseUrl}${raw}`;
    return raw;
  });

  const breadcrumbItems = $derived(pageData?.breadcrumbItems ?? []);

  const faviconUrl = $derived(data.logoUrl ?? '/favicon.svg');
  const faviconType = $derived(
    faviconUrl.split('?')[0].toLowerCase().endsWith('.svg') ? 'image/svg+xml' : 'image/png'
  );

  const robotsContent = $derived.by(() => {
    const base = (pageData?.robots ?? 'index, follow').trim();
    if (/noindex/i.test(base)) return base;
    return `${base}, max-image-preview:large, max-snippet:-1`;
  });
  const topBannerData = $derived(pageData?.topBanner ?? null);

  // Ein Preload pro Breakpoint-Variante (media-Attribut), Format: WebP.
  // AVIF wäre kleiner, aber ein type-Mismatch (Browser ohne AVIF) macht den
  // Preload wirkungslos — WebP greift überall. Browser laden nur den Preload,
  // dessen media-Query matcht.
  const bannerPreloads = $derived.by(() => {
    const r = topBannerData?.responsive;
    if (!r) return [];
    type Src = { type: string; srcset: string; media?: string };
    const sources = r.sources as Src[];
    const byMedia = new Map<string, Src>();
    for (const s of sources) {
      const key = s.media ?? '';
      const existing = byMedia.get(key);
      if (!existing || (existing.type !== 'image/webp' && s.type === 'image/webp')) {
        if (s.type === 'image/webp' || !existing) byMedia.set(key, s);
      }
    }
    return [...byMedia.values()].map((s) => ({
      href: r.fallback,
      srcset: s.srcset,
      type: s.type,
      media: s.media,
    }));
  });

  function escapeLdJson(s: string): string {
    return s.replace(/<\/script/gi, '<\\/script');
  }
  const jsonLdScript = $derived(
    `<script type="application/ld+json">${escapeLdJson(JSON.stringify({
      '@context': 'https://schema.org',
      '@type': 'WebSite',
      name: data.siteName,
      url: baseUrl,
      inLanguage: 'de-DE',
      publisher: { '@type': 'Organization', name: data.siteName, ...(baseUrl ? { '@id': `${baseUrl}#org` } : {}) },
    }))}<\/script>`,
  );
  const organizationLdScript = $derived.by(() => {
    const sameAs = (data.socialLinks ?? [])
      .map((l) => l.href)
      .filter((h) => /^https?:\/\//.test(h));
    const org: Record<string, unknown> = {
      '@context': 'https://schema.org',
      '@type': 'Organization',
      ...(baseUrl ? { '@id': `${baseUrl}#org` } : {}),
      name: data.siteName,
      url: baseUrl,
      ...(data.logoSocialImage ? { logo: data.logoSocialImage } : {}),
      ...(sameAs.length ? { sameAs } : {}),
    };
    return `<script type="application/ld+json">${escapeLdJson(JSON.stringify(org))}<\/script>`;
  });
  const pageJsonLdScripts = $derived.by(() => {
    const raw = pageData?.jsonLd;
    if (!raw) return '';
    const items = Array.isArray(raw) ? raw : [raw];
    return items
      .map(
        (o) =>
          `<script type="application/ld+json">${escapeLdJson(JSON.stringify(o))}<\/script>`,
      )
      .join('');
  });
  const breadcrumbJsonLdScript = $derived.by(() => {
    const items = pageData?.breadcrumbItems ?? [];
    if (items.length < 2) return '';
    const ld = {
      '@context': 'https://schema.org',
      '@type': 'BreadcrumbList',
      itemListElement: items.map((item, i) => ({
        '@type': 'ListItem',
        position: i + 1,
        name: item.label,
        ...(item.href
          ? {
              item: item.href.startsWith('http')
                ? item.href
                : `${baseUrl}${item.href}`,
            }
          : {}),
      })),
    };
    return `<script type="application/ld+json">${escapeLdJson(JSON.stringify(ld))}<\/script>`;
  });

  const formbricksAppUrl = String(import.meta.env.PUBLIC_FORMBRICKS_APP_URL ?? '').replace(/\/$/, '');
  const formbricksEnvId = String(import.meta.env.PUBLIC_FORMBRICKS_ENVIRONMENT_ID ?? '').trim();
  const formbricksScript =
    formbricksAppUrl && formbricksEnvId
      ? `<script>(function(){var appUrl=${JSON.stringify(formbricksAppUrl)};var environmentId=${JSON.stringify(formbricksEnvId)};if(!appUrl||!environmentId)return;var t=document.createElement('script');t.type='text/javascript';t.async=true;t.src=appUrl+'/js/formbricks.umd.cjs';var e=document.getElementsByTagName('script')[0];if(e&&e.parentNode)e.parentNode.insertBefore(t,e);setTimeout(function(){if(window.formbricks&&typeof window.formbricks.setup==='function'){window.formbricks.setup({environmentId:environmentId,appUrl:appUrl});}},500);})();<\/script>`
      : '';
</script>

<svelte:head>
  {#if isEmbed}
    <!-- Embed-Modus: minimaler Head, kein OG/JSON-LD/Analytics. Page setzt
         eigenen <title> und robots-meta. -->
    <link rel="icon" type={faviconType} href={faviconUrl} />
  {:else}
    <meta name="theme-color" content="#ffffff" />
    <meta name="robots" content={robotsContent} />
    {#each bannerPreloads as p (p.media ?? p.type)}
      <link
        rel="preload"
        as="image"
        href={p.href}
        imagesrcset={p.srcset}
        imagesizes="100vw"
        type={p.type}
        media={p.media}
        fetchpriority="high"
      />
    {/each}
    <link rel="icon" type={faviconType} href={faviconUrl} />
    <link rel="apple-touch-icon" href={faviconUrl} />
    <link rel="alternate" type="application/rss+xml" title="Beiträge" href="/posts/rss.xml" />
    <link rel="sitemap" href="/sitemap.xml" />
    <title>{seoTitle}</title>
    {#if seoDescription}
      <meta name="description" content={seoDescription} />
    {/if}
    {#if pageData?.keywords}
      <meta name="keywords" content={pageData.keywords} />
    {/if}
    <link rel="canonical" href={canonical} />
    <!-- Open Graph -->
    <meta property="og:type" content={pageData?.ogType ?? "website"} />
    <meta property="og:url" content={canonical} />
    <meta property="og:title" content={seoTitle} />
    {#if seoDescription}
      <meta property="og:description" content={seoDescription} />
    {/if}
    {#if socialImageUrl}
      <meta property="og:image" content={socialImageUrl} />
      <meta property="og:image:width" content={String(SOCIAL_IMAGE_DIMENSIONS.width)} />
      <meta property="og:image:height" content={String(SOCIAL_IMAGE_DIMENSIONS.height)} />
      {#if pageData?.ogImageAlt}
        <meta property="og:image:alt" content={pageData.ogImageAlt} />
      {/if}
    {/if}
    <meta property="og:locale" content="de_DE" />
    <meta property="og:site_name" content={data.siteName} />
    {#if pageData?.articlePublishedTime}
      <meta property="article:published_time" content={pageData.articlePublishedTime} />
    {/if}
    {#if pageData?.articleModifiedTime}
      <meta property="article:modified_time" content={pageData.articleModifiedTime} />
    {/if}
    {#if pageData?.articleAuthor}
      <meta property="article:author" content={pageData.articleAuthor} />
    {/if}
    {#each pageData?.articleTags ?? [] as tag}
      <meta property="article:tag" content={tag} />
    {/each}
    <!-- Twitter -->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:url" content={canonical} />
    <meta name="twitter:title" content={seoTitle} />
    {#if seoDescription}
      <meta name="twitter:description" content={seoDescription} />
    {/if}
    {#if socialImageUrl}
      <meta name="twitter:image" content={socialImageUrl} />
      {#if pageData?.ogImageAlt}
        <meta name="twitter:image:alt" content={pageData.ogImageAlt} />
      {/if}
    {/if}
    {#if pageData?.twitterLabel1 && pageData?.twitterData1}
      <meta name="twitter:label1" content={pageData.twitterLabel1} />
      <meta name="twitter:data1" content={pageData.twitterData1} />
    {/if}
    <!-- JSON-LD WebSite + Organization -->
    {@html jsonLdScript}
    {@html organizationLdScript}
    {#if breadcrumbJsonLdScript}
      {@html breadcrumbJsonLdScript}
    {/if}
    {#if pageJsonLdScripts}
      {@html pageJsonLdScripts}
    {/if}
    {#if import.meta.env.PUBLIC_UMAMI_SCRIPT_URL && import.meta.env.PUBLIC_UMAMI_WEBSITE_ID}
      <script
        defer
        src={import.meta.env.PUBLIC_UMAMI_SCRIPT_URL}
        data-website-id={import.meta.env.PUBLIC_UMAMI_WEBSITE_ID}
      ></script>
    {/if}
    {#if data.analyticsPm86SiteId}
      <script
        defer
        src="https://analytics.pm86.de/api/script.js"
        data-site-id={data.analyticsPm86SiteId}
      ></script>
    {/if}
    {#if formbricksScript}
      {@html formbricksScript}
    {/if}
  {/if}
</svelte:head>

<TranslationProvider translations={data.translations}>
  {#if isEmbed}
    {@render children()}
  {:else}
    <a
      href="#main-content"
      class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[100] focus:bg-white focus:px-3 focus:py-2 focus:shadow focus:outline focus:outline-2 focus:outline-wald-600 focus:rounded-xs"
    >Zum Inhalt springen</a>
    <div class="flex min-h-screen flex-col text-stein-900">
      {#if deadlineActive && data.deadlineBanner}
        <DeadlineBannerBlock block={data.deadlineBanner} />
      {:else if data.announcementBanner}
        <AnnouncementBanner banner={data.announcementBanner} />
      {/if}
      {#if pageData?.preview || pageData?.previewDraft}
        <div
          class="sticky top-0 z-[90] w-full bg-erde-500 text-black shadow-sm"
          role="status"
          aria-live="polite"
        >
          <div class="container-custom flex items-center justify-between gap-3 py-1.5 text-sm">
            <span class="font-semibold">
              {pageData?.previewDraft ? 'Live-Preview · ungespeicherter Draft' : 'Preview-Modus · Draft sichtbar (nicht indexiert)'}
            </span>
            <a
              href={$page.url.pathname}
              class="underline hover:no-underline"
              rel="nofollow"
            >
              Preview verlassen
            </a>
          </div>
        </div>
      {/if}
      <div class="print:hidden">
        <Header
          links={data.headerLinks}
          socialLinks={data.socialLinks}
          logoUrl={data.logoUrl}
          logoSvgHtml={data.logoSvgHtml}
          translations={data.translations}
        />
        <HeaderOverlay />
      </div>

      {#if topBannerData}
        <div class="print:hidden">
          <TopBanner
            banner={topBannerData.banner as import('$lib/cms').FullwidthBannerEntry | null}
            resolvedImages={topBannerData.resolvedImages}
            responsive={topBannerData.responsive ?? null}
            focalCss={topBannerData.focalCss ?? null}
            headline={topBannerData.headline}
            subheadline={topBannerData.subheadline}
          />
        </div>
      {/if}

      <main id="main-content" tabindex="-1" class="flex-1 min-h-[60em] print:min-h-0">
        <div class="container-custom pb-12 print:pb-0">
          {#if breadcrumbItems.length > 0}
            <div class="print:hidden">
              <Breadcrumbs items={breadcrumbItems} />
            </div>
          {/if}
          <!-- Konsolidierter Top-Abstand vorm ersten Content-Element (alle
               Seitentypen), zusätzlich zum Breadcrumb-py. -->
          <div class="pt-4 md:pt-6">
            {@render children()}
          </div>
        </div>
      </main>

      <div class="print:hidden">
        <Footer
          footer={data.footerData}
          translations={data.translations}
          logoSvgHtml={data.logoSvgHtml}
          logoUrl={data.logoUrl}
          siteName={data.siteName}
        />
      </div>
    </div>

    <ContentModal
      modals={data.modals}
      pathname={$page.url.pathname}
      translations={data.translations}
    />
  {/if}
</TranslationProvider>
