'use client';

import { useState, useEffect, useMemo } from 'react';
import type { PhotoAttachment } from '../../types/api/photos';

const CYCLE_INTERVAL_MIN_MS = 6000;
const CYCLE_INTERVAL_MAX_MS = 8000;
export const CROSSFADE_DURATION_MS = 600;

export interface CycledImage {
  url: string;
  alt: string;
}

export interface UseImageCycleResult {
  list: CycledImage[];
  currentIndex: number;
  nextIndex: number;
  transitioning: boolean;
}

/** Stable value in [0, 1) derived from seed string (FNV-1a hash). Same seed always produces same value. */
function seedToUnit(seed: string): number {
  let h = 2166136261 >>> 0;
  for (let i = 0; i < seed.length; i++) {
    h ^= seed.charCodeAt(i);
    h = (Math.imul(h, 16777619) >>> 0) >>> 0;
  }
  return (h >>> 0) / 4294967296;
}

/** Seeded Fisher-Yates shuffle. Same seed produces same order (SSR-safe). */
function shuffleWithSeed<T>(array: T[], seed: string): T[] {
  if (array.length <= 1) return array;
  const arr = [...array];
  let h = 2166136261 >>> 0;
  for (let i = 0; i < seed.length; i++) {
    h ^= seed.charCodeAt(i);
    h = (Math.imul(h, 16777619) >>> 0) >>> 0;
  }
  const next = (step: number) => {
    h = (Math.imul(1664525, (h + step) >>> 0) + 1013904223) >>> 0;
    return (h >>> 0) / 4294967296;
  };
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(next(i) * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]];
  }
  return arr;
}

function photoUrlFromAttachment(pa: PhotoAttachment): string | undefined {
  return pa.photo?.large_url || pa.photo?.medium_url || pa.photo?.thumbnail_url;
}

function photoAltFromAttachment(pa: PhotoAttachment): string {
  return pa.photo?.alt_text || pa.photo?.title || '';
}

/**
 * Cycles through a list of photo attachments with a seeded shuffle and crossfade transitions.
 *
 * Each card uses a unique seed so intervals are staggered — cards don't all transition in sync.
 * The shuffle is deterministic (SSR-safe) and the timer only activates when there are 2+ images.
 */
export function useImageCycle(
  photoAttachments: PhotoAttachment[] | undefined,
  seed: string
): UseImageCycleResult {
  const list = useMemo<CycledImage[]>(() => {
    const arr = Array.isArray(photoAttachments) && photoAttachments.length > 0 ? photoAttachments : [];
    if (arr.length === 0) return [];
    return shuffleWithSeed(arr, seed)
      .map((pa) => ({ url: photoUrlFromAttachment(pa) ?? '', alt: photoAltFromAttachment(pa) }))
      .filter((x) => x.url);
  }, [photoAttachments, seed]);

  const [currentIndex, setCurrentIndex] = useState(0);
  const [transitioning, setTransitioning] = useState(false);

  // Per-card random interval (6–8 s) so cards don't all transition in sync
  const intervalMs = useMemo(
    () => CYCLE_INTERVAL_MIN_MS + Math.floor(seedToUnit(seed) * (CYCLE_INTERVAL_MAX_MS - CYCLE_INTERVAL_MIN_MS + 1)),
    [seed]
  );

  useEffect(() => {
    if (list.length <= 1) return;
    const id = setInterval(() => setTransitioning(true), intervalMs);
    return () => clearInterval(id);
  }, [list.length, intervalMs]);

  useEffect(() => {
    if (!transitioning || list.length <= 1) return;
    const t = setTimeout(() => {
      setCurrentIndex((i) => (i + 1) % list.length);
      setTransitioning(false);
    }, CROSSFADE_DURATION_MS);
    return () => clearTimeout(t);
  }, [transitioning, list.length]);

  const nextIndex = list.length > 1 ? (currentIndex + 1) % list.length : 0;

  return { list, currentIndex, nextIndex, transitioning };
}
