"use client";

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

export type VideoCardData = {
  id: string;
  title: string;
  thumbnailUrl: string | null;
  durationSeconds: number;
  views: number;
  likeCount?: number;
  isLive?: boolean;
  isShort?: boolean;
  isAgeRestricted?: boolean;
  visibility?: string;
  status?: string;
  progressSeconds?: number | null;
  publishedAt?: Date | string | null;
  createdAt?: Date | string;
  channel: { id: string; name: string; handle: string; avatarUrl: string | null; isVerified?: boolean };
  channelSubscriberCount?: number;
};

export function VideoCard({ video, layout = "grid", showChannel = true }: { video: VideoCardData; layout?: "grid" | "row"; showChannel?: boolean }) {
  const { user } = useSession();
  const { toast, toastNode } = useToast();
  const [menuOpen, setMenuOpen] = useState(false);
  const [saveOpen, setSaveOpen] = useState(false);
  const [reportOpen, setReportOpen] = useState(false);
  const [playlists, setPlaylists] = useState<{ id: string; title: string; isSystem: string | null }[]>([]);
  const [newPlaylist, setNewPlaylist] = useState("");

  const date = video.publishedAt ?? video.createdAt ?? new Date();
  const progress = video.progressSeconds && video.durationSeconds ? Math.min(100, (video.progressSeconds / video.durationSeconds) * 100) : 0;

  const openSave = async () => {
    setMenuOpen(false);
    if (!user) return toast("Sign in to save videos");
    try {
      const data = await api<{ items: { id: string; title: string; isSystem: string | null }[] }>("/api/playlists");
      setPlaylists(data.items.filter((p) => p.isSystem !== "history"));
      setSaveOpen(true);
    } catch (error) {
      toast(error instanceof Error ? error.message : "Could not load playlists");
    }
  };

  const saveTo = async (playlistId: string) => {
    try {
      await api(`/api/playlists/${playlistId}`, { method: "POST", json: { videoId: video.id } });
      toast("Saved to playlist");
      setSaveOpen(false);
    } catch (error) {
      toast(error instanceof Error ? error.message : "Could not save");
    }
  };

  const createAndSave = async () => {
    if (!newPlaylist.trim()) return;
    try {
      const created = await api<{ playlist: { id: string } }>("/api/playlists", {
        method: "POST",
        json: { title: newPlaylist.trim(), visibility: "private" },
      });
      await saveTo(created.playlist.id);
      setNewPlaylist("");
    } catch (error) {
      toast(error instanceof Error ? error.message : "Could not create playlist");
    }
  };

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

  const report = async (reason: string) => {
    try {
      await api(`/api/videos/${video.id}/report`, { method: "POST", json: { targetType: "video", targetId: video.id, reason } });
      toast("Report submitted — thanks for keeping PlayTube safe");
      setReportOpen(false);
    } catch (error) {
      toast(error instanceof Error ? error.message : "Could not report");
    }
  };

  const thumb = (
    <div className={`relative ${layout === "row" ? "w-40 shrink-0 sm:w-64" : "w-full"} aspect-video overflow-hidden rounded-xl bg-surface`}>
      {video.thumbnailUrl ? (
        // eslint-disable-next-line @next/next/no-img-element
        <img src={video.thumbnailUrl} alt="" loading="lazy" className="h-full w-full object-cover transition duration-300 hover:scale-105" />
      ) : (
        <div className="grid h-full w-full place-items-center bg-gradient-to-br from-surface to-surface-hover text-3xl">🎬</div>
      )}
      <span className="absolute bottom-1 right-1 rounded bg-black/85 px-1 py-0.5 text-[11px] font-semibold text-white">
        {video.isLive ? <span className="text-brand">● LIVE</span> : formatDuration(video.durationSeconds)}
      </span>
      {video.isAgeRestricted ? (
        <span className="absolute left-1 top-1 rounded bg-black/80 px-1 py-0.5 text-[10px] font-bold text-white">18+</span>
      ) : null}
      {progress > 0 ? (
        <span className="absolute inset-x-0 bottom-0 h-1 bg-white/30">
          <span className="block h-full bg-brand" style={{ width: `${progress}%` }} />
        </span>
      ) : null}
    </div>
  );

  return (
    <div className={layout === "row" ? "flex gap-3" : "group space-y-3"}>
      <Link href={`/watch/${video.id}`} className={layout === "row" ? "shrink-0" : "block"}>
        {thumb}
      </Link>
      <div className="flex min-w-0 flex-1 gap-3">
        {showChannel && layout === "grid" ? (
          <Link href={`/channel/${video.channel.handle}`} className="shrink-0">
            <Avatar name={video.channel.name} src={video.channel.avatarUrl} size={36} />
          </Link>
        ) : null}
        <div className="min-w-0 flex-1">
          <Link href={`/watch/${video.id}`}>
            <h3 className="line-clamp-2 text-sm font-semibold leading-snug">{video.title}</h3>
          </Link>
          {showChannel ? (
            <Link href={`/channel/${video.channel.handle}`} className="mt-1 flex items-center gap-1 text-xs text-muted hover:text-fg">
              <span className="truncate">{video.channel.name}</span>
              {video.channel.isVerified ? <span aria-label="verified">✔️</span> : null}
            </Link>
          ) : null}
          <p className="text-xs text-muted">
            {formatCount(video.views)} views · {timeAgo(date)}
            {video.visibility && video.visibility !== "public" ? ` · ${video.visibility}` : ""}
          </p>
          {video.status && video.status !== "ready" ? (
            <p className="mt-1 text-xs font-medium text-brand">
              {video.status === "processing" ? `Processing ${video.durationSeconds ? "" : "…"}` : video.status}
            </p>
          ) : null}
        </div>
        <div className="relative shrink-0">
          <button
            aria-label="Video options"
            onClick={() => setMenuOpen((v) => !v)}
            className="grid h-8 w-8 place-items-center rounded-full text-muted hover:bg-surface"
          >
            ⋮
          </button>
          {menuOpen ? (
            <div className="absolute right-0 top-9 z-30 w-52 overflow-hidden rounded-xl border border-line bg-bg-elevated py-1 text-sm shadow-2xl">
              <button onClick={() => void openSave()} className="flex w-full items-center gap-3 px-3 py-2 hover:bg-surface">
                💾 Save to playlist
              </button>
              <button onClick={share} className="flex w-full items-center gap-3 px-3 py-2 hover:bg-surface">
                🔗 Share / copy link
              </button>
              <button
                onClick={() => {
                  setMenuOpen(false);
                  void api(`/api/videos/${video.id}/progress`, { method: "POST", json: { positionSeconds: 0, durationSeconds: video.durationSeconds } });
                  toast("Removed from continue watching");
                }}
                className="flex w-full items-center gap-3 px-3 py-2 hover:bg-surface"
              >
                🚫 Not interested
              </button>
              <button
                onClick={() => {
                  setMenuOpen(false);
                  if (!user) return toast("Sign in to report");
                  setReportOpen(true);
                }}
                className="flex w-full items-center gap-3 px-3 py-2 hover:bg-surface"
              >
                🚩 Report
              </button>
            </div>
          ) : null}
        </div>
      </div>

      <Modal open={saveOpen} onClose={() => setSaveOpen(false)} title="Save video to...">
        <div className="space-y-1">
          {playlists.map((playlist) => (
            <button key={playlist.id} onClick={() => void saveTo(playlist.id)} className="flex w-full items-center justify-between rounded-lg px-3 py-2 text-left text-sm hover:bg-surface">
              <span>{playlist.title}</span>
              <span className="text-muted">{playlist.isSystem ? "auto" : "playlist"}</span>
            </button>
          ))}
        </div>
        <div className="mt-4 flex gap-2 border-t border-line pt-4">
          <input
            value={newPlaylist}
            onChange={(event) => setNewPlaylist(event.target.value)}
            placeholder="New playlist name"
            className="flex-1 rounded-lg border border-line bg-surface px-3 py-2 text-sm"
          />
          <Button onClick={() => void createAndSave()} size="sm">Create</Button>
        </div>
      </Modal>

      <Modal open={reportOpen} onClose={() => setReportOpen(false)} title="Report video">
        <div className="space-y-1">
          {REPORT_REASONS.map((reason) => (
            <button key={reason.value} onClick={() => void report(reason.value)} className="w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-surface">
              {reason.label}
            </button>
          ))}
        </div>
      </Modal>
      {toastNode}
    </div>
  );
}
