"use client";

import { useEffect, useRef, useState } from "react";
import Link from "next/link";
import { Avatar } from "./Avatar";
import { sfx } from "@/lib/sfx";
import { firework } from "@/lib/particles";
import type { User, Reel } from "@/lib/types";

/** Retries a couple of times — API routes can be slow on a cold start. */
function useFetchList<T>(url: string, take = 8) {
  const [items, setItems] = useState<T[]>([]);
  useEffect(() => {
    let stop = false;
    // Poll until we get data. Routes can be slow to compile on first hit,
    // and an aborted StrictMode double-mount shouldn't leave this empty.
    async function load(attempt = 0) {
      if (stop) return;
      try {
        const r = await fetch(url);
        const d = r.ok ? await r.json() : [];
        if (Array.isArray(d) && d.length > 0) {
          setItems(d.slice(0, take));
          return;
        }
      } catch {
        /* retry below */
      }
      if (attempt < 8) setTimeout(() => load(attempt + 1), 800);
    }
    load();
    return () => {
      // Deliberately do NOT cancel in-flight retries here: React's dev-mode
      // double mount would otherwise leave the list permanently empty.
      stop = false;
    };
  }, [url, take]);
  return items;
}

/** ›/‹ toggle — scrolls the row to the end and back. */
function useNavToggle() {
  const rowRef = useRef<HTMLDivElement>(null);
  const [expanded, setExpanded] = useState(false);
  function toggle() {
    const row = rowRef.current;
    if (!row) return;
    row.scrollTo({ left: expanded ? 0 : row.scrollWidth, behavior: "smooth" });
    setExpanded((v) => !v);
  }
  return { rowRef, expanded, toggle };
}

export function PeopleYouMightKnow() {
  const people = useFetchList<User>("/api/users/suggested", 8);
  const [added, setAdded] = useState<Set<string>>(new Set());
  const { rowRef, expanded, toggle } = useNavToggle();

  if (people.length === 0) return null;

  function onAdd(e: React.MouseEvent<HTMLButtonElement>, u: User) {
    const btn = e.currentTarget;
    if (added.has(u.id)) {
      setAdded((s) => {
        const n = new Set(s);
        n.delete(u.id);
        return n;
      });
      return;
    }
    setAdded((s) => new Set(s).add(u.id));
    sfx.friend();
    firework(btn, ["#7dff8a", "#2fd573", "#b9ffd0", "#ffffff"]);
    fetch(`/api/users/${u.username}/follow`, { method: "POST" }).catch(() => {});
  }

  return (
    <section className="fs-sec">
      <div className="fs-head">
        <span className="fs-icon friends">
          <svg viewBox="0 0 24 24">
            <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
            <circle cx="9" cy="7" r="4" />
            <path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" />
          </svg>
        </span>
        <span className="fs-title">People you may know</span>
        <button className="fs-nav" onClick={toggle} title={expanded ? "Back" : "More"}>
          {expanded ? "‹" : "›"}
        </button>
      </div>
      <div className="fs-row" ref={rowRef}>
        {people.map((u) => (
          <div key={u.id} className="fs-person">
            <Link href={`/${u.username}`} className="fs-av">
              {/* The size is set here, not in CSS: Avatar writes width
                  and height as inline styles, so a class trying to shrink
                  it lost and the face spilled over the name underneath. */}
              <Avatar user={u} size={46} effect={false} />
            </Link>
            <span className="fs-name">{u.name}</span>
            <span className="fs-mut">
              {u.mutualCount
                ? `${u.mutualCount} mutual friend${u.mutualCount === 1 ? "" : "s"}`
                : ""}
            </span>
            <button
              className={`fs-add ${added.has(u.id) ? "done" : ""}`}
              onClick={(e) => onAdd(e, u)}
            >
              {added.has(u.id) ? "Added ✓" : "Add Friend"}
            </button>
          </div>
        ))}
      </div>
    </section>
  );
}

const REEL_EMOJI = ["💃", "🛹", "🍕", "🐶", "🎮", "🌊", "🎸", "✨"];

function fmt(v: number) {
  return v >= 1e6 ? `${(v / 1e6).toFixed(1)}M` : v >= 1000 ? `${(v / 1000).toFixed(1)}K` : String(v);
}

/** Counts up from zero when the strip first appears. */
function ViewCount({ to }: { to: number }) {
  const [n, setN] = useState(0);
  useEffect(() => {
    const t0 = performance.now();
    let raf = 0;
    const step = (t: number) => {
      const k = Math.min(1, (t - t0) / 1200);
      setN(Math.floor(to * (k * (2 - k))));
      if (k < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [to]);
  return <>{fmt(n)}</>;
}

export function ReelsStrip() {
  const reels = useFetchList<Reel>("/api/reels", 8);
  const { rowRef, expanded, toggle } = useNavToggle();

  if (reels.length === 0) return null;

  return (
    <section className="fs-sec">
      <div className="fs-head">
        <span className="fs-icon reels">
          <svg viewBox="0 0 24 24">
            <rect x="2" y="2" width="20" height="20" rx="2.18" />
            <path d="M7 2v20M17 2v20M2 12h20M2 7h5M2 17h5M17 17h5M17 7h5" />
          </svg>
        </span>
        <span className="fs-title">Reels</span>
        <span className="fs-sub">trending now 🔥</span>
        <button className="fs-nav" onClick={toggle} title={expanded ? "Back" : "More"}>
          {expanded ? "‹" : "›"}
        </button>
      </div>
      <div className="fs-row" ref={rowRef}>
        {reels.map((r, i) => (
          <Link key={r.id} href="/reels" className={`fs-reel bg-gradient-to-br ${r.gradient}`}>
            <span className="fs-remoji">{REEL_EMOJI[i % REEL_EMOJI.length]}</span>
            <span className="fs-play">▶</span>
            <span className="fs-views">
              ▶ <ViewCount to={r.views} />
            </span>
            <span className="fs-dur">0:{String(18 + ((i * 7) % 40)).padStart(2, "0")}</span>
            <span className="fs-user">
              <Avatar user={r.author} size={20} />
              <span className="fs-uname">{r.author.username}</span>
            </span>
          </Link>
        ))}
      </div>
    </section>
  );
}
