<script lang="ts">
  import { onMount } from 'svelte';
  
  interface Props {
    onRefresh: () => Promise<void>;
    threshold?: number;
    children?: any;
  }
  
  let { onRefresh, threshold = 80, children }: Props = $props();
  
  let container: HTMLDivElement;
  let startY = 0;
  let currentY = 0;
  let pulling = $state(false);
  let releasing = $state(false);
  let refreshing = $state(false);
  let pullDistance = $state(0);
  
  let pullProgress = $derived(Math.min(pullDistance / threshold, 1));
  let canRefresh = $derived(pullProgress >= 1 && !refreshing);
  
  function handleTouchStart(e: TouchEvent) {
    if (container.scrollTop !== 0 || refreshing) return;
    
    startY = e.touches[0].clientY;
    pulling = true;
  }
  
  function handleTouchMove(e: TouchEvent) {
    if (!pulling || refreshing) return;
    
    currentY = e.touches[0].clientY;
    const diff = currentY - startY;
    
    if (diff > 0 && container.scrollTop === 0) {
      e.preventDefault();
      pullDistance = diff * 0.5; // Add resistance
    }
  }
  
  async function handleTouchEnd() {
    if (!pulling) return;
    
    pulling = false;
    
    if (canRefresh) {
      releasing = true;
      refreshing = true;
      
      try {
        await onRefresh();
      } finally {
        refreshing = false;
        setTimeout(() => {
          releasing = false;
          pullDistance = 0;
        }, 300);
      }
    } else {
      releasing = true;
      setTimeout(() => {
        releasing = false;
        pullDistance = 0;
      }, 300);
    }
  }
  
  onMount(() => {
    // Also handle mouse events for desktop testing
    function handleMouseDown(e: MouseEvent) {
      if (container.scrollTop !== 0 || refreshing) return;
      startY = e.clientY;
      pulling = true;
    }
    
    function handleMouseMove(e: MouseEvent) {
      if (!pulling || refreshing) return;
      
      currentY = e.clientY;
      const diff = currentY - startY;
      
      if (diff > 0 && container.scrollTop === 0) {
        e.preventDefault();
        pullDistance = diff * 0.5;
      }
    }
    
    function handleMouseUp() {
      handleTouchEnd();
    }
    
    container.addEventListener('mousedown', handleMouseDown);
    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('mouseup', handleMouseUp);
    
    return () => {
      container?.removeEventListener('mousedown', handleMouseDown);
      window.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('mouseup', handleMouseUp);
    };
  });
</script>

<div class="pull-to-refresh-container">
  <div 
    class="pull-indicator"
    class:pulling
    class:releasing
    class:refreshing
    style="transform: translateY({refreshing ? threshold : pullDistance}px)"
  >
    <div class="spinner-container" style="transform: rotate({pullProgress * 180}deg)">
      {#if refreshing}
        <div class="spinner"></div>
      {:else}
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83" 
                opacity={pullProgress} />
        </svg>
      {/if}
    </div>
    <div class="pull-text">
      {#if refreshing}
        Refreshing...
      {:else if canRefresh}
        Release to refresh
      {:else}
        Pull to refresh
      {/if}
    </div>
  </div>
  
  <div 
    bind:this={container}
    class="content-container"
    class:pulling
    on:touchstart={handleTouchStart}
    on:touchmove={handleTouchMove}
    on:touchend={handleTouchEnd}
    style="transform: translateY({refreshing ? threshold : pullDistance}px)"
  >
    {@render children?.()}
  </div>
</div>

<style>
  .pull-to-refresh-container {
    position: relative;
    height: 100%;
    overflow: hidden;
  }
  
  .content-container {
    height: 100%;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    transition: transform 0.3s ease;
  }
  
  .content-container.pulling {
    transition: none;
  }
  
  .pull-indicator {
    position: absolute;
    top: -60px;
    left: 0;
    right: 0;
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    transition: transform 0.3s ease;
    z-index: 10;
  }
  
  .pull-indicator.pulling {
    transition: none;
  }
  
  .spinner-container {
    transition: transform 0.2s ease;
  }
  
  .spinner {
    width: 24px;
    height: 24px;
    border: 2px solid #e0e0e0;
    border-top-color: #007bff;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
  }
  
  @keyframes spin {
    to { transform: rotate(360deg); }
  }
  
  .pull-text {
    font-size: 14px;
    color: #666;
    white-space: nowrap;
  }
</style>