<script lang="ts">
  // Phase 9. Progressive-disclosure wrapper around the native <details>
  // element. The chevron animates on open via a CSS transform; height
  // animation uses interpolate-size where the engine supports it
  // (modern Chromium / WebKit), and falls back to instant open/close
  // elsewhere. prefers-reduced-motion disables both.
  import { ChevronRight } from "lucide-svelte";
  import type { Component } from "svelte";

  interface Props {
    title: string;
    description?: string;
    open?: boolean;
    onopen?: () => void;
    icon?: Component<{ size?: number; class?: string; "aria-hidden"?: boolean | "true" | "false" }>;
    children?: import("svelte").Snippet;
  }

  let { title, description = "", open = false, onopen, icon: Icon, children }: Props = $props();

  // Fires once on the first transition from closed → open. Used by
  // sections that lazy-load expensive data (e.g. TTS voice enumeration).
  // Plain let (not $state) — the flag is mutated only by the toggle
  // handler and never has to be reactive in the template.
  let hasOpened = false;
  let detailsEl: HTMLDetailsElement | null = $state(null);

  function handleToggle(event: Event) {
    const el = event.currentTarget as HTMLDetailsElement | null;
    if (el?.open && !hasOpened) {
      hasOpened = true;
      onopen?.();
    }
  }

  // Push prop changes to the DOM. The native <details> open attribute
  // is mutated by user interaction outside Svelte's reactive graph;
  // when the parent later changes the open prop (for example because a
  // search filter expanded a different group), $effect force-syncs.
  // User-driven toggles where the prop value did not change keep their
  // local state because $effect only re-runs on prop diff.
  $effect(() => {
    if (detailsEl && detailsEl.open !== open) detailsEl.open = open;
  });
</script>

<details bind:this={detailsEl} {open} ontoggle={handleToggle} class="settings-group border-t border-border-subtle">
  <summary
    class="flex items-start gap-2 cursor-pointer list-none py-3 px-1 rounded hover:bg-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-accent"
  >
    <ChevronRight
      class="chevron size-4 mt-1 shrink-0 text-text-tertiary"
      aria-hidden="true"
    />
    {#if Icon}
      <Icon size={16} class="mt-1 shrink-0 text-text-tertiary" aria-hidden="true" />
    {/if}
    <div class="flex-1">
      <p class="text-sm text-text font-semibold">{title}</p>
      {#if description}
        <p class="text-[12px] text-text-secondary tracking-wide mt-1">{description}</p>
      {/if}
    </div>
  </summary>
  <div class="pl-6 pr-2 pb-3">
    {@render children?.()}
  </div>
</details>

<style>
  .settings-group :global(summary)::-webkit-details-marker {
    display: none;
  }
  :global(.chevron) {
    transition: transform 180ms ease;
  }
  details[open] > summary :global(.chevron) {
    transform: rotate(90deg);
  }

  @media (prefers-reduced-motion: reduce) {
    :global(.chevron) {
      transition: none;
    }
  }
</style>
