<script lang="ts">
  import { marked } from "$lib/markdown-safe";
  import Icon from "@iconify/svelte";
  import "$lib/iconify-offline";
  import { getBlockLayoutClasses } from "$lib/block-layout";
  import type { OrganisationsBlockData, OrganisationEntry } from "$lib/block-types";
  import { extractCmsImageField } from "$lib/rusty-image";
  import Card from "$lib/components/Card.svelte";
  import Badge from "$lib/components/Badge.svelte";
  import RustyImage from "$lib/components/RustyImage.svelte";
  import Button from "$lib/ui/Button.svelte";

  function organisationLogoField(o: OrganisationEntry) {
    return extractCmsImageField(o.logo);
  }

  function organisationLogoAlt(o: OrganisationEntry): string {
    if (o.logo && typeof o.logo === "object" && o.logo.description) {
      return o.logo.description;
    }
    return o.name ?? "";
  }

  let { block }: { block: OrganisationsBlockData } = $props();

  const layoutClasses = $derived(
    block.layout ? getBlockLayoutClasses(block.layout) : "col-span-12 mb-4",
  );
  const compact = $derived(block.presentation === "compact");
  const carousel = $derived(block.presentation === "carousel");
  const orgs = $derived(block.organisations ?? []);
  const ctaHtml = $derived(
    block.addOrganisationMarkdown
      ? (marked.parse(block.addOrganisationMarkdown) as string)
      : ""
  );

  const addOrganisationCtaLink = $derived.by(() => {
    const raw = block.addOrganisationLink;
    if (!raw || typeof raw !== "object") return undefined;
    const url = typeof raw.url === "string" ? raw.url.trim() : "";
    if (!url) return undefined;
    const linkName =
      typeof raw.linkName === "string" && raw.linkName.trim() !== ""
        ? raw.linkName.trim()
        : url;
    return { url, linkName, newTab: Boolean(raw.newTab) };
  });

  const showAddOrganisationCard = $derived(
    Boolean(
      block.addOrganisationTitle?.trim() ||
        block.addOrganisationMarkdown?.trim() ||
        addOrganisationCtaLink
    )
  );

  let scroller: HTMLDivElement | undefined = $state();
  function scrollByPage(dir: 1 | -1) {
    if (!scroller) return;
    scroller.scrollBy({ left: scroller.clientWidth * dir * 0.9, behavior: "smooth" });
  }
</script>

{#snippet defaultCard(o: OrganisationEntry, linkUrl: string | undefined, logoField: ReturnType<typeof organisationLogoField>, orgIndex: number)}
  <Card href={linkUrl} class="h-full">
    <div class="flex h-11 w-11 shrink-0 items-center justify-center overflow-hidden bg-stein-100">
      {#if logoField}
        <RustyImage
          src={logoField.url}
          focal={logoField.focal ?? null}
          width={88}
          aspect="1/1"
          fit="contain"
          quality={85}
          alt={organisationLogoAlt(o)}
          class="h-full w-full object-contain p-0.5"
          loading="lazy"
        />
      {:else}
        {@const fishMaskId = `org-logo-fallback-mask-${orgIndex}`}
        <svg class="h-8 w-8 text-stein-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true">
          <defs>
            <mask id={fishMaskId}>
              <g fill="none">
                <path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M24 30v14" />
                <path fill="#555555" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M29 23c11 5 16 14 16 14s-12 0-21-8c-9 8-21 8-21 8s5-10 16-14c0-13 5-19 5-19s5 6 5 19" />
                <circle cx="24" cy="24" r="2" fill="#fff" />
              </g>
            </mask>
          </defs>
          <path fill="currentColor" d="M0 0h48v48H0z" mask={`url(#${fishMaskId})`} />
        </svg>
      {/if}
    </div>
    {#if o.badge && typeof o.badge === "object" && o.badge.label}
      <div class="absolute top-2 right-2">
        <Badge color={o.badge.color}>{o.badge.label}</Badge>
      </div>
    {/if}
    <h5 class="mb-1 min-w-0 truncate text-sm font-medium leading-tight text-stein-900">{o.name ?? ""}</h5>
    {#if o.description}
      <p class="line-clamp-2 text-xs font-light text-stein-600">{o.description}</p>
    {/if}
  </Card>
{/snippet}

{#snippet ctaCard()}
  <Card
    variant="callout"
    href={addOrganisationCtaLink?.url}
    target={addOrganisationCtaLink?.newTab ? "_blank" : undefined}
    rel={addOrganisationCtaLink?.newTab ? "noopener noreferrer" : undefined}
    class="h-full w-full max-w-full md:max-w-md"
  >
    {#if block.addOrganisationTitle}
      <h5 class="text-xl font-semibold text-wald-800 leading-snug">{block.addOrganisationTitle}</h5>
    {/if}
    {#if ctaHtml}
      <div class="markdown text-xs text-wald-700">{@html ctaHtml}</div>
    {/if}
    {#if addOrganisationCtaLink}
      <div class="self-start">
        <Button variant="primary" size="sm">
          {addOrganisationCtaLink.linkName}
        </Button>
      </div>
    {/if}
  </Card>
{/snippet}

<div class={layoutClasses} data-block="Organisations" data-block-type="organisations" data-block-slug={block._slug}>
  {#if block.headline}
    <h3
      class={compact ? "mb-2 text-lg font-semibold text-stein-900" : "mb-4"}
    >{block.headline}</h3>
  {/if}

  {#if carousel}
    <div class="relative">
      <div
        bind:this={scroller}
        class="flex gap-4 overflow-x-auto scroll-smooth snap-x snap-mandatory pb-2 [scrollbar-width:thin]"
      >
        {#each orgs as org, orgIndex}
          {#if typeof org === "object" && org !== null}
            {@const o = org as OrganisationEntry}
            {@const linkUrl =
              typeof o.link === "object" &&
              o.link !== null &&
              typeof o.link.url === "string" &&
              o.link.url.trim() !== ""
                ? o.link.url.trim()
                : undefined}
            {@const logoField = organisationLogoField(o)}
            <div
              class="shrink-0 snap-start w-[calc((100%-1rem)/2)] lg:w-[calc((100%-2rem)/3)]"
            >
              {@render defaultCard(o, linkUrl, logoField, orgIndex)}
            </div>
          {/if}
        {/each}
      </div>
      {#if orgs.length > 2}
        <button
          type="button"
          onclick={() => scrollByPage(-1)}
          aria-label="Vorherige Organisationen"
          class="hidden md:flex absolute -left-3 top-1/2 -translate-y-1/2 -translate-x-1/2 size-7 items-center justify-center rounded-full bg-white border border-stein-200 shadow-md hover:bg-stein-50 transition"
        >
          <Icon icon="mdi:chevron-left" class="size-4" aria-hidden="true" />
        </button>
        <button
          type="button"
          onclick={() => scrollByPage(1)}
          aria-label="Weitere Organisationen"
          class="hidden md:flex absolute -right-3 top-1/2 -translate-y-1/2 translate-x-1/2 size-7 items-center justify-center rounded-full bg-white border border-stein-200 shadow-md hover:bg-stein-50 transition"
        >
          <Icon icon="mdi:chevron-right" class="size-4" aria-hidden="true" />
        </button>
      {/if}
    </div>
    {#if showAddOrganisationCard}
      <div class="mt-2 min-w-0">
        {@render ctaCard()}
      </div>
    {/if}
  {:else}
    <div
      class={compact
        ? "grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3"
        : "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3"}
    >
      {#each orgs as org, orgIndex}
        {#if typeof org === "object" && org !== null}
          {@const o = org as OrganisationEntry}
          {@const linkUrl =
            typeof o.link === "object" &&
            o.link !== null &&
            typeof o.link.url === "string" &&
            o.link.url.trim() !== ""
              ? o.link.url.trim()
              : undefined}
          {@const logoField = organisationLogoField(o)}
          {#if compact}
            <Card href={linkUrl} layout="inline" class="h-full">
              <div class="flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden bg-stein-100">
                {#if logoField}
                  <RustyImage
                    src={logoField.url}
                    focal={logoField.focal ?? null}
                    width={80}
                    aspect="1/1"
                    fit="contain"
                    quality={85}
                    alt={organisationLogoAlt(o)}
                    class="h-full w-full object-contain p-0.5"
                    loading="lazy"
                  />
                {:else}
                  {@const fishMaskId = `org-logo-fallback-mask-c-${orgIndex}`}
                  <svg class="h-7 w-7 text-stein-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true">
                    <defs>
                      <mask id={fishMaskId}>
                        <g fill="none">
                          <path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M24 30v14" />
                          <path fill="#555555" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M29 23c11 5 16 14 16 14s-12 0-21-8c-9 8-21 8-21 8s5-10 16-14c0-13 5-19 5-19s5 6 5 19" />
                          <circle cx="24" cy="24" r="2" fill="#fff" />
                        </g>
                      </mask>
                    </defs>
                    <path fill="currentColor" d="M0 0h48v48H0z" mask={`url(#${fishMaskId})`} />
                  </svg>
                {/if}
              </div>
              <div class="flex min-w-0 flex-1 flex-col gap-0.5">
                <h5 class="text-sm font-medium leading-tight text-stein-900">{o.name ?? ""}</h5>
                {#if o.description}
                  <p class="line-clamp-2 text-xs font-light text-stein-600">{o.description}</p>
                {/if}
              </div>
            </Card>
          {:else}
            {@render defaultCard(o, linkUrl, logoField, orgIndex)}
          {/if}
        {/if}
      {/each}

      {#if showAddOrganisationCard}
        {@render ctaCard()}
      {/if}
    </div>
  {/if}
</div>
