<script lang="ts">
  import { cn } from '$lib/utils'
  import type { Snippet } from 'svelte'

  interface Props {
    class?: string
    className?: string
    orientation?: 'vertical' | 'horizontal' | 'both'
    type?: 'auto' | 'always' | 'scroll' | 'hover'
    fadeMask?: boolean
    children?: Snippet
  }

  let {
    class: classFromClass,
    className,
    orientation = 'vertical',
    type = 'auto',
    fadeMask = true,
    children,
    ...rest
  }: Props = $props()

  // Support both class and className props
  const finalClass = classFromClass || className

  // Track scroll position for dynamic fade masks
  let viewportEl: HTMLDivElement | null = $state(null)
  let canScrollUp = $state(false)
  let canScrollDown = $state(false)

  function checkScroll() {
    if (!viewportEl) return
    const { scrollTop, scrollHeight, clientHeight } = viewportEl
    canScrollUp = scrollTop > 5
    canScrollDown = scrollTop < scrollHeight - clientHeight - 5
  }

  $effect(() => {
    if (!viewportEl || !fadeMask) return

    // Initial check
    checkScroll()

    // Use ResizeObserver to detect content changes
    const resizeObserver = new ResizeObserver(checkScroll)
    resizeObserver.observe(viewportEl)
    if (viewportEl.firstElementChild) {
      resizeObserver.observe(viewportEl.firstElementChild)
    }

    return () => resizeObserver.disconnect()
  })
</script>

<div
  data-slot="scroll-area"
  class={cn('relative', finalClass)}
  {...rest}
>
  <div
    bind:this={viewportEl}
    onscroll={checkScroll}
    data-slot="scroll-area-viewport"
    data-fade-top={fadeMask && orientation !== 'horizontal' && canScrollUp}
    data-fade-bottom={fadeMask && orientation !== 'horizontal' && canScrollDown}
    class={cn(
      'size-full rounded-[inherit]',
      orientation === 'vertical' && 'overflow-y-auto overflow-x-hidden',
      orientation === 'horizontal' && 'overflow-x-auto overflow-y-hidden',
      orientation === 'both' && 'overflow-auto',
      type === 'always' && 'scrollbar-thin',
      type === 'hover' && 'scrollbar-thin hover:scrollbar-thumb-border',
      type === 'auto' && 'scrollbar-thin'
    )}
  >
    {#if children}
      {@render children()}
    {/if}
  </div>
</div>

<style>
  /* Fade mask - only bottom (at top of scroll) */
  [data-slot="scroll-area-viewport"][data-fade-top="false"][data-fade-bottom="true"] {
    mask-image: linear-gradient(
      to bottom,
      black,
      black calc(100% - 20px),
      transparent
    );
    -webkit-mask-image: linear-gradient(
      to bottom,
      black,
      black calc(100% - 20px),
      transparent
    );
  }

  /* Fade mask - only top (at bottom of scroll) */
  [data-slot="scroll-area-viewport"][data-fade-top="true"][data-fade-bottom="false"] {
    mask-image: linear-gradient(
      to bottom,
      transparent,
      black 20px,
      black
    );
    -webkit-mask-image: linear-gradient(
      to bottom,
      transparent,
      black 20px,
      black
    );
  }

  /* Fade mask - both top and bottom (in the middle) */
  [data-slot="scroll-area-viewport"][data-fade-top="true"][data-fade-bottom="true"] {
    mask-image: linear-gradient(
      to bottom,
      transparent,
      black 20px,
      black calc(100% - 20px),
      transparent
    );
    -webkit-mask-image: linear-gradient(
      to bottom,
      transparent,
      black 20px,
      black calc(100% - 20px),
      transparent
    );
  }

  /* More visible scrollbar */
  [data-slot="scroll-area-viewport"] {
    scrollbar-width: thin;
    scrollbar-color: var(--muted-foreground) var(--muted);
  }

  [data-slot="scroll-area-viewport"]::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }

  [data-slot="scroll-area-viewport"]::-webkit-scrollbar-track {
    background: var(--muted);
    border-radius: 9999px;
  }

  [data-slot="scroll-area-viewport"]::-webkit-scrollbar-thumb {
    background-color: var(--muted-foreground);
    border-radius: 9999px;
    border: 2px solid var(--muted);
    background-clip: content-box;
  }

  [data-slot="scroll-area-viewport"]::-webkit-scrollbar-thumb:hover {
    background-color: var(--foreground);
  }
</style>
