"use client";

import { Children, cloneElement, isValidElement, ReactNode } from "react";

/* ------------------------------------------------------------------ */
/*  ShimmerSkeleton                                                   */
/* ------------------------------------------------------------------ */

interface ShimmerSkeletonProps {
  className?: string;
  width?: string | number;
  height?: string | number;
  rounded?: "sm" | "md" | "lg" | "xl" | "2xl" | "full";
  variant?: "text" | "circle" | "card" | "rect";
}

const roundedMap: Record<string, string> = {
  sm: "rounded-sm",
  md: "rounded-md",
  lg: "rounded-lg",
  xl: "rounded-xl",
  "2xl": "rounded-2xl",
  full: "rounded-full",
};

const variantDefaults: Record<
  string,
  { width?: string | number; height?: string | number; rounded: string }
> = {
  text: { width: "100%", height: "1em", rounded: "rounded" },
  circle: { width: 40, height: 40, rounded: "rounded-full" },
  card: { width: "100%", height: 120, rounded: "rounded-xl" },
  rect: { width: "100%", height: 40, rounded: "rounded-md" },
};

export function ShimmerSkeleton({
  className = "",
  width,
  height,
  rounded,
  variant = "rect",
}: ShimmerSkeletonProps) {
  const defaults = variantDefaults[variant] ?? variantDefaults.rect;
  const resolvedWidth = width ?? defaults?.width ?? "100%";
  const resolvedHeight = height ?? defaults?.height ?? 40;
  const resolvedRounded = rounded
    ? roundedMap[rounded] ?? "rounded-md"
    : defaults?.rounded ?? "rounded-md";

  return (
    <div
      className={`shimmer-skeleton ${resolvedRounded} ${className}`}
      style={{
        width:
          typeof resolvedWidth === "number"
            ? `${resolvedWidth}px`
            : resolvedWidth,
        height:
          typeof resolvedHeight === "number"
            ? `${resolvedHeight}px`
            : resolvedHeight,
      }}
    />
  );
}

/* ------------------------------------------------------------------ */
/*  ShimmerGroup – staggers children entrance by 50ms each            */
/* ------------------------------------------------------------------ */

interface ShimmerGroupProps {
  children: ReactNode;
  staggerMs?: number;
  className?: string;
}

export function ShimmerGroup({
  children,
  staggerMs = 50,
  className,
}: ShimmerGroupProps) {
  return (
    <div className={className}>
      {Children.map(children, (child, index) => {
        if (!isValidElement(child)) return child;
        return cloneElement(child as React.ReactElement<{ style?: React.CSSProperties }>, {
          style: {
            ...(child.props as { style?: React.CSSProperties }).style,
            animationDelay: `${index * staggerMs}ms`,
          },
        });
      })}
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  Inline <style> – injected once via a hidden element               */
/* ------------------------------------------------------------------ */

const shimmerCSS = `
.shimmer-skeleton {
  position: relative;
  overflow: hidden;
  background: var(--shimmer-bg, #e5e7eb);
}

@media (prefers-color-scheme: dark) {
  .shimmer-skeleton {
    --shimmer-bg: #374151;
    --shimmer-highlight: rgba(255, 255, 255, 0.06);
  }
}

:root {
  --shimmer-bg: #e5e7eb;
  --shimmer-highlight: rgba(255, 255, 255, 0.5);
}

.dark .shimmer-skeleton {
  --shimmer-bg: #374151;
  --shimmer-highlight: rgba(255, 255, 255, 0.06);
}

.shimmer-skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    110deg,
    transparent 25%,
    var(--shimmer-highlight) 50%,
    transparent 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s ease-in-out infinite;
}

@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}
`;

/**
 * Mount this once (e.g. in a layout) to inject shimmer styles,
 * or simply import ShimmerSkeleton — the styles tag is rendered
 * alongside the first skeleton automatically.
 */
export function ShimmerStyles() {
  return <style dangerouslySetInnerHTML={{ __html: shimmerCSS }} />;
}
