"use client";

import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { Avatar, Button, useToast } from "@/components/ui";
import { useSession } from "@/components/session-provider";
import { api } from "@/lib/api-client";
import { formatCount } from "@/lib/format";

export type ShortItem = {
  id: string;
  title: string;
  description?: string;
  mp4Url: string | null;
  hlsUrl: string | null;
  thumbnailUrl: string | null;
  views: number;
  likeCount: number;
  dislikeCount?: number;
  commentCount?: number;
  audioTrackName?: string | null;
  liked?: boolean;
  channel: { id: string; name: string; handle: string; avatarUrl: string | null; isVerified?: boolean };
};

export function ShortsFeed({ initialItems }: { initialItems: ShortItem[] }) {
  const { user } = useSession();
  const { toast, toastNode } = useToast();
  const [items, setItems] = useState(initialItems);
  const [activeIndex, setActiveIndex] = useState(0);
  const [commentOpen, setCommentOpen] = useState(false);
  const [comments, setComments] = useState<{ id: string; body: string; author: { name: string; avatarUrl: string | null }; createdAt: string }[]>([]);
  const [commentText, setCommentText] = useState("");
  const containerRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const node = containerRef.current;
    if (!node) return;
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          const video = entry.target.querySelector("video");
          if (video) {
            if (entry.isIntersecting) void video.play().catch(() => undefined);
            else video.pause();
          }
          if (entry.isIntersecting) {
            const index = Number((entry.target as HTMLElement).dataset.index);
            setActiveIndex(index);
          }
        });
      },
      { threshold: 0.6 },
    );
    node.querySelectorAll("[data-short]").forEach((el) => observer.observe(el));
    return () => observer.disconnect();
  }, [items.length]);

  useEffect(() => {
    void api<{ items: ShortItem[] }>("/api/videos?shorts=1&limit=20&offset=20")
      .then((data) => setItems((prev) => [...prev, ...data.items.filter((i) => !prev.some((p) => p.id === i.id))]))
      .catch(() => undefined);
  }, []);

  const active = items[activeIndex];

  const like = async (short: ShortItem) => {
    if (!user) return toast("Sign in to like shorts");
    setItems((prev) =>
      prev.map((item) =>
        item.id === short.id ? { ...item, liked: !item.liked, likeCount: item.likeCount + (item.liked ? -1 : 1) } : item,
      ),
    );
    await api(`/api/videos/${short.id}/reaction`, { method: "POST", json: { type: "like" } }).catch(() => undefined);
  };

  const subscribe = async (short: ShortItem) => {
    if (!user) return toast("Sign in to subscribe");
    await api(`/api/channels/${short.channel.handle}`, { method: "POST" }).catch((error) => toast(error.message));
    toast(`Subscribed to ${short.channel.name}`);
  };

  const share = async (short: ShortItem) => {
    const url = `${window.location.origin}/watch/${short.id}`;
    try {
      if (navigator.share) await navigator.share({ title: short.title, url });
      else {
        await navigator.clipboard.writeText(url);
        toast("Link copied");
      }
    } catch {
      /* cancelled */
    }
  };

  const openComments = async (short: ShortItem) => {
    setCommentOpen(true);
    const data = await api<{ items: typeof comments }>(`/api/comments?videoId=${short.id}`).catch(() => ({ items: [] }));
    setComments(data.items);
  };

  const postComment = async () => {
    if (!active || !commentText.trim()) return;
    if (!user) return toast("Sign in to comment");
    await api("/api/comments", { method: "POST", json: { videoId: active.id, body: commentText } }).catch((e) => toast(e.message));
    const data = await api<{ items: typeof comments }>(`/api/comments?videoId=${active.id}`).catch(() => ({ items: [] }));
    setComments(data.items);
    setCommentText("");
  };

  return (
    <div ref={containerRef} className="no-scrollbar h-[calc(100dvh-3.5rem)] snap-y snap-mandatory overflow-y-auto">
      {items.length === 0 ? (
        <div className="grid h-full place-items-center text-sm text-muted">No shorts yet — upload the first one!</div>
      ) : null}
      {items.map((short, index) => (
        <section key={short.id} data-short data-index={index} className="relative flex h-[calc(100dvh-3.5rem)] snap-start items-center justify-center">
          <div className="relative h-full w-full max-w-[420px] overflow-hidden bg-black sm:rounded-2xl">
            <video
              src={short.mp4Url ?? undefined}
              poster={short.thumbnailUrl ?? undefined}
              loop
              playsInline
              muted
              className="h-full w-full object-cover"
              onClick={(event) => {
                const el = event.currentTarget;
                if (el.paused) void el.play();
                else el.pause();
              }}
            />
            <div className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/90 to-transparent p-4 pb-20 text-white">
              <div className="flex items-center gap-2">
                <Link href={`/channel/${short.channel.handle}`} className="flex items-center gap-2">
                  <Avatar name={short.channel.name} src={short.channel.avatarUrl} size={32} />
                  <span className="text-sm font-semibold">{short.channel.handle}</span>
                </Link>
                <Button size="sm" variant="primary" onClick={() => void subscribe(short)}>
                  Subscribe
                </Button>
              </div>
              <p className="mt-2 line-clamp-2 text-sm">{short.title}</p>
              {short.audioTrackName ? (
                <p className="mt-1 text-xs text-white/70">🎵 {short.audioTrackName}</p>
              ) : null}
              <p className="mt-1 text-xs text-white/70">{formatCount(short.views)} views</p>
            </div>

            <div className="absolute bottom-24 right-3 flex flex-col items-center gap-4 text-white">
              <button onClick={() => void like(short)} className="flex flex-col items-center text-xs">
                <span className={`grid h-11 w-11 place-items-center rounded-full bg-white/15 text-xl ${short.liked ? "text-brand" : ""}`}>
                  {short.liked ? "❤️" : "🤍"}
                </span>
                {formatCount(short.likeCount)}
              </button>
              <button onClick={() => void openComments(short)} className="flex flex-col items-center text-xs">
                <span className="grid h-11 w-11 place-items-center rounded-full bg-white/15 text-xl">💬</span>
                {formatCount(short.commentCount ?? 0)}
              </button>
              <button onClick={() => void share(short)} className="flex flex-col items-center text-xs">
                <span className="grid h-11 w-11 place-items-center rounded-full bg-white/15 text-xl">↗️</span>
                Share
              </button>
            </div>
          </div>
        </section>
      ))}

      {commentOpen && active ? (
        <div className="fixed inset-0 z-[90] flex items-end bg-black/60" onClick={() => setCommentOpen(false)}>
          <div className="max-h-[70vh] w-full overflow-y-auto rounded-t-2xl bg-bg-elevated p-4" onClick={(event) => event.stopPropagation()}>
            <h3 className="mb-3 font-semibold">Comments</h3>
            <div className="mb-3 flex gap-2">
              <input
                value={commentText}
                onChange={(event) => setCommentText(event.target.value)}
                placeholder="Add a comment"
                className="flex-1 rounded-full border border-line bg-surface px-4 py-2 text-sm"
              />
              <Button size="sm" onClick={() => void postComment()}>Post</Button>
            </div>
            <div className="space-y-3">
              {comments.length === 0 ? <p className="text-sm text-muted">Be the first to comment.</p> : null}
              {comments.map((comment) => (
                <div key={comment.id} className="flex gap-3">
                  <Avatar name={comment.author.name} src={comment.author.avatarUrl} size={32} />
                  <div>
                    <p className="text-xs font-semibold">{comment.author.name}</p>
                    <p className="text-sm">{comment.body}</p>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      ) : null}
      {toastNode}
    </div>
  );
}
