"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import { VideoPlayer } from "@/components/video-player";
import { VideoCard, type VideoCardData } from "@/components/video-card";
import { Avatar, Button, Modal, Spinner, useToast } from "@/components/ui";
import { useSession } from "@/components/session-provider";
import { api } from "@/lib/api-client";
import { formatCount, formatDate, timeAgo } from "@/lib/format";
import { REPORT_REASONS } from "@/lib/constants";

type CommentItem = {
  id: string;
  body: string;
  likeCount: number;
  replyCount: number;
  isPinned: boolean;
  heartedByCreator: boolean;
  createdAt: string | Date;
  liked: boolean;
  author: { id: string; name: string; handle: string; avatarUrl: string | null };
  replies: CommentItem[];
};

type WatchVideo = VideoCardData & {
  description: string;
  tags: string[];
  mp4Url: string | null;
  hlsUrl: string | null;
  dislikeCount: number;
  commentCount: number;
  chapters: { time: number; title: string }[];
  captions: { lang: string; label: string; cues: { start: number; end: number; text: string }[] }[];
  renditions: { id: number; label: string; height: number; bitrateKbps: number; url: string }[];
  monetized: boolean;
  copyrightStatus: string;
  scheduledFor?: string | Date | null;
  viewerReaction: string;
  subscribed: boolean;
  channel: VideoCardData["channel"] & {
    description: string | null;
    subscriberCount?: number;
    bannerUrl: string | null;
    ownerUserId: string;
  };
};

type Ad = { id: string; advertiserName: string; headline: string; body: string; targetUrl: string } | null;

export function WatchView({
  video: initialVideo,
  related,
  comments: initialComments,
  playlist,
  isOwner,
  signedIn,
}: {
  video: WatchVideo;
  related: VideoCardData[];
  comments: CommentItem[];
  playlist: { playlist: { id: string; title: string; itemCount: number }; items: VideoCardData[] } | null;
  isOwner: boolean;
  signedIn: boolean;
}) {
  const { user, t } = useSession();
  const { toast, toastNode } = useToast();
  const [video, setVideo] = useState(initialVideo);
  const [theater, setTheater] = useState(false);
  const [expanded, setExpanded] = useState(false);
  const [reaction, setReaction] = useState(initialVideo.viewerReaction);
  const [likes, setLikes] = useState(initialVideo.likeCount ?? 0);
  const [dislikes, setDislikes] = useState(initialVideo.dislikeCount ?? 0);
  const [subscribed, setSubscribed] = useState(initialVideo.subscribed);
  const [notify, setNotify] = useState(true);
  const [comments, setComments] = useState(initialComments);
  const [commentSort, setCommentSort] = useState<"top" | "new">("top");
  const [commentText, setCommentText] = useState("");
  const [replyTo, setReplyTo] = useState<string | null>(null);
  const [reportOpen, setReportOpen] = useState(false);
  const [saveOpen, setSaveOpen] = useState(false);
  const [playlists, setPlaylists] = useState<{ id: string; title: string; isSystem: string | null }[]>([]);
  const [ad, setAd] = useState<Ad>(null);
  const [adVisible, setAdVisible] = useState(false);
  const [ageOk, setAgeOk] = useState(false);
  const [memberOpen, setMemberOpen] = useState(false);
  const [thanksOpen, setThanksOpen] = useState(false);

  const gate = video.isAgeRestricted && !ageOk;

  useEffect(() => {
    try {
      setAgeOk(localStorage.getItem("playtube-adult") === "1");
    } catch {}
    void api(`/api/videos/${video.id}/view`, { method: "POST" }).catch(() => undefined);
    void api<{ ad: Ad }>(`/api/ads?placement=preroll&videoId=${video.id}`)
      .then((data) => {
        if (data.ad) {
          setAd(data.ad);
          setAdVisible(true);
          setTimeout(() => setAdVisible(false), 6000);
        }
      })
      .catch(() => undefined);
  }, [video.id]);

  const react = async (type: "like" | "dislike") => {
    if (!user) return toast("Sign in to rate videos");
    const next = reaction === type ? "none" : type;
    setReaction(next);
    setLikes((v) => v + (next === "like" ? 1 : reaction === "like" ? -1 : 0));
    setDislikes((v) => v + (next === "dislike" ? 1 : reaction === "dislike" ? -1 : 0));
    const data = await api<{ likeCount: number; dislikeCount: number }>(`/api/videos/${video.id}/reaction`, {
      method: "POST",
      json: { type: next },
    }).catch(() => null);
    if (data) {
      setLikes(data.likeCount);
      setDislikes(data.dislikeCount);
    }
  };

  const toggleSubscribe = async () => {
    if (!user) return toast("Sign in to subscribe");
    const data = await api<{ subscribed: boolean; subscriberCount: number; notify?: boolean }>(`/api/channels/${video.channel.handle}`, {
      method: "POST",
    }).catch((error) => {
      toast(error.message);
      return null;
    });
    if (data) {
      setSubscribed(data.subscribed);
      setNotify(Boolean(data.notify));
      toast(data.subscribed ? `Subscribed to ${video.channel.name}` : "Subscription removed");
    }
  };

  const saveProgress = async (seconds: number) => {
    if (!user) return;
    await api(`/api/videos/${video.id}/progress`, {
      method: "POST",
      json: { positionSeconds: Math.round(seconds), durationSeconds: Math.round(video.durationSeconds) },
    }).catch(() => undefined);
  };

  const postComment = async (parentId?: string) => {
    if (!user) return toast("Sign in to comment");
    const body = parentId ? (document.getElementById(`reply-${parentId}`) as HTMLInputElement)?.value : commentText;
    if (!body?.trim()) return;
    const data = await api<{ items: CommentItem[] }>("/api/comments", {
      method: "POST",
      json: { videoId: video.id, body, parentId },
    }).catch((error) => {
      toast(error.message);
      return null;
    });
    if (data) {
      setComments(data.items);
      setCommentText("");
      setReplyTo(null);
      toast("Comment posted");
    }
  };

  const reloadComments = async (sort = commentSort) => {
    const data = await api<{ items: CommentItem[] }>(`/api/comments?videoId=${video.id}&sort=${sort}`).catch(() => null);
    if (data) setComments(data.items);
  };

  const commentAction = async (comment: CommentItem, action: "like" | "pin" | "heart" | "delete" | "report") => {
    if (!user) return toast("Sign in first");
    if (action === "report") {
      await api(`/api/comments/${comment.id}/report`, { method: "POST", json: { targetType: "comment", targetId: comment.id, reason: "spam" } });
      return toast("Comment reported");
    }
    const data = await api<{ liked?: boolean; likeCount?: number }>(`/api/comments/${comment.id}/${action}`, { method: "POST" }).catch(() => null);
    if (data?.likeCount !== undefined) {
      setComments((prev) => prev.map((c) => (c.id === comment.id ? { ...c, likeCount: data.likeCount!, liked: Boolean(data.liked) } : c)));
    } else {
      await reloadComments();
      toast(action === "pin" ? "Pinned comment updated" : action === "heart" ? "Creator heart updated" : "Comment removed");
    }
  };

  const openSave = async () => {
    if (!user) return toast("Sign in to save");
    const data = await api<{ items: { id: string; title: string; isSystem: string | null }[] }>("/api/playlists").catch(() => null);
    if (data) {
      setPlaylists(data.items.filter((p) => p.isSystem !== "history"));
      setSaveOpen(true);
    }
  };

  const saveTo = async (playlistId: string) => {
    await api(`/api/playlists/${playlistId}`, { method: "POST", json: { videoId: video.id } }).catch((e) => toast(e.message));
    toast("Saved");
    setSaveOpen(false);
  };

  const share = async () => {
    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 {
      /* cancelled */
    }
  };

  const joinMembership = async () => {
    if (!user) return toast("Sign in to become a member");
    await api("/api/monetization", { method: "POST", json: { action: "join", channelId: video.channel.id } }).catch((e) => toast(e.message));
    toast("Membership started — thanks for the support!");
    setMemberOpen(false);
  };

  const sendThanks = async (amountCents: number) => {
    if (!user) return toast("Sign in first");
    await api("/api/monetization", { method: "POST", json: { action: "super-thanks", channelId: video.channel.id, amountCents, videoId: video.id } }).catch((e) => toast(e.message));
    toast("Super Thanks sent 💖");
    setThanksOpen(false);
  };

  const playerVideo = useMemo(
    () => ({
      id: video.id,
      title: video.title,
      mp4Url: video.mp4Url,
      hlsUrl: video.hlsUrl,
      thumbnailUrl: video.thumbnailUrl,
      durationSeconds: video.durationSeconds,
      chapters: video.chapters ?? [],
      captions: video.captions ?? [],
      renditions: video.renditions ?? [],
      progressSeconds: video.progressSeconds ?? null,
    }),
    [video],
  );

  const nextVideo = related[0];

  return (
    <div className={`mx-auto flex w-full flex-col gap-6 px-2 pt-2 sm:px-6 ${theater ? "" : "xl:flex-row"}`}>
      <div className="min-w-0 flex-1">
        <VideoPlayer
          video={playerVideo}
          theater={theater}
          onToggleTheater={() => setTheater((v) => !v)}
          onProgress={signedIn ? saveProgress : undefined}
          onNext={nextVideo ? () => { window.location.href = `/watch/${nextVideo.id}`; } : undefined}
        />

        {adVisible && ad ? (
          <div className="mt-2 flex items-center justify-between gap-3 rounded-xl border border-brand/40 bg-brand/10 p-3 text-sm">
            <div className="min-w-0">
              <p className="truncate font-semibold text-brand">Ad · {ad.advertiserName}</p>
              <p className="truncate text-muted">{ad.headline}</p>
            </div>
            <div className="flex shrink-0 gap-2">
              <a
                href={ad.targetUrl}
                target="_blank"
                rel="noopener noreferrer sponsored"
                onClick={() => void api("/api/ads", { method: "POST", json: { id: ad.id, videoId: video.id } })}
                className="rounded-full bg-brand px-3 py-1.5 font-semibold text-white"
              >
                Visit
              </a>
              <button onClick={() => setAdVisible(false)} className="rounded-full bg-surface px-3 py-1.5 font-medium">
                Skip
              </button>
            </div>
          </div>
        ) : null}

        <h1 className="mt-3 text-lg font-bold leading-snug sm:text-xl">{video.title}</h1>

        <div className="mt-3 flex flex-wrap items-center gap-3">
          <Link href={`/channel/${video.channel.handle}`} className="flex items-center gap-3">
            <Avatar name={video.channel.name} src={video.channel.avatarUrl} size={40} />
            <div>
              <p className="flex items-center gap-1 text-sm font-semibold">
                {video.channel.name}
                {video.channel.isVerified ? <span aria-label="verified">✔️</span> : null}
              </p>
              <p className="text-xs text-muted">{formatCount(video.channel.subscriberCount ?? 0)} subscribers</p>
            </div>
          </Link>

          {!isOwner ? (
            <Button variant={subscribed ? "secondary" : "primary"} onClick={() => void toggleSubscribe()}>
              {subscribed ? `${t("subscribed")} ${notify ? "🔔" : "🔕"}` : t("subscribe")}
            </Button>
          ) : (
            <Link href="/studio/content" className="rounded-full bg-surface px-4 py-2 text-sm font-semibold">
              Manage video
            </Link>
          )}
          {subscribed ? (
            <button
              onClick={async () => {
                const data = await api<{ notify: boolean }>(`/api/channels/${video.channel.handle}?mode=notify`, {
                  method: "POST",
                  json: { notify: !notify },
                }).catch(() => null);
                if (data) {
                  setNotify(data.notify);
                  toast(data.notify ? "All notifications on" : "Notifications off");
                }
              }}
              className="rounded-full bg-surface px-3 py-2 text-sm"
            >
              {notify ? "🔔 All" : "🔕 Personalized"}
            </button>
          ) : null}

          <button onClick={() => setMemberOpen(true)} className="rounded-full bg-surface px-3 py-2 text-sm font-semibold">
            💎 Join
          </button>

          <div className="ml-auto flex flex-wrap items-center gap-2">
            <div className="flex items-center overflow-hidden rounded-full bg-surface">
              <button onClick={() => void react("like")} className={`flex items-center gap-2 px-4 py-2 text-sm font-medium hover:bg-surface-hover ${reaction === "like" ? "text-brand" : ""}`}>
                👍 {formatCount(likes)}
              </button>
              <span className="h-6 w-px bg-line" />
              <button onClick={() => void react("dislike")} className={`px-4 py-2 text-sm font-medium hover:bg-surface-hover ${reaction === "dislike" ? "text-brand" : ""}`}>
                👎 {formatCount(dislikes)}
              </button>
            </div>
            <button onClick={share} className="flex items-center gap-2 rounded-full bg-surface px-4 py-2 text-sm font-medium hover:bg-surface-hover">
              ↗️ {t("share")}
            </button>
            <button onClick={() => void openSave()} className="flex items-center gap-2 rounded-full bg-surface px-4 py-2 text-sm font-medium hover:bg-surface-hover">
              💾 {t("save")}
            </button>
            <button onClick={() => setThanksOpen(true)} className="rounded-full bg-surface px-4 py-2 text-sm font-medium hover:bg-surface-hover">
              💖 Thanks
            </button>
            <button onClick={() => setReportOpen(true)} className="rounded-full bg-surface px-4 py-2 text-sm font-medium hover:bg-surface-hover">
              🚩
            </button>
          </div>
        </div>

        <div className="mt-4 rounded-xl bg-surface p-4 text-sm">
          <p className="font-semibold">
            {formatCount(video.views)} views · {video.publishedAt ? timeAgo(video.publishedAt) : "not published yet"}
            {video.copyrightStatus !== "clear" ? ` · © ${video.copyrightStatus}` : ""}
          </p>
          <p className={`mt-2 whitespace-pre-line break-words ${expanded ? "" : "line-clamp-3"}`}>{video.description || "No description"}</p>
          {video.tags?.length ? (
            <div className="mt-3 flex flex-wrap gap-2">
              {video.tags.map((tag) => (
                <Link key={tag} href={`/results?q=${encodeURIComponent(tag)}`} className="text-xs font-medium text-brand">
                  #{tag}
                </Link>
              ))}
            </div>
          ) : null}
          <button onClick={() => setExpanded((v) => !v)} className="mt-2 text-xs font-semibold text-muted">
            {expanded ? "Show less" : "Show more"}
          </button>
          {video.renditions?.length ? (
            <p className="mt-3 text-xs text-muted">
              Available qualities: {video.renditions.map((r) => r.label).join(", ")}
            </p>
          ) : null}
        </div>

        {/* comments */}
        <section className="mt-6">
          <div className="mb-4 flex items-center gap-4">
            <h2 className="text-base font-bold">{formatCount(video.commentCount)} {t("comments")}</h2>
            <div className="flex gap-2">
              {(["top", "new"] as const).map((sort) => (
                <button
                  key={sort}
                  onClick={() => {
                    setCommentSort(sort);
                    void reloadComments(sort);
                  }}
                  className={`rounded-full px-3 py-1 text-xs font-semibold ${commentSort === sort ? "bg-fg text-bg" : "bg-chip text-muted"}`}
                >
                  {sort === "top" ? "Top comments" : "Newest first"}
                </button>
              ))}
            </div>
          </div>

          {user ? (
            <div className="mb-6 flex gap-3">
              <Avatar name={user.displayName} src={user.avatarUrl} size={40} />
              <div className="flex-1">
                <input
                  value={commentText}
                  onChange={(event) => setCommentText(event.target.value)}
                  placeholder="Add a comment..."
                  className="w-full border-b border-line bg-transparent pb-2 text-sm outline-none focus:border-brand"
                />
                <div className="mt-2 flex justify-end gap-2">
                  <Button variant="ghost" size="sm" onClick={() => setCommentText("")}>Cancel</Button>
                  <Button size="sm" onClick={() => void postComment()} disabled={!commentText.trim()}>Comment</Button>
                </div>
              </div>
            </div>
          ) : (
            <p className="mb-6 rounded-xl bg-surface p-4 text-sm text-muted">
              <Link href="/login" className="font-semibold text-brand">Sign in</Link> to join the conversation.
            </p>
          )}

          <div className="space-y-5">
            {comments.length === 0 ? <p className="text-sm text-muted">No comments yet.</p> : null}
            {comments.map((comment) => (
              <div key={comment.id} className="flex gap-3">
                <Avatar name={comment.author.name} src={comment.author.avatarUrl} size={40} />
                <div className="min-w-0 flex-1">
                  <p className="flex flex-wrap items-center gap-2 text-xs text-muted">
                    <span className="font-semibold text-fg">@{comment.author.handle}</span>
                    {comment.isPinned ? <span className="rounded bg-chip px-1.5 py-0.5 text-[10px] font-bold">PINNED</span> : null}
                    <span>{timeAgo(comment.createdAt)}</span>
                  </p>
                  <p className="mt-1 whitespace-pre-line break-words text-sm">{comment.body}</p>
                  <div className="mt-1.5 flex items-center gap-3 text-xs text-muted">
                    <button onClick={() => void commentAction(comment, "like")} className={comment.liked ? "font-bold text-brand" : ""}>
                      👍 {formatCount(comment.likeCount)}
                    </button>
                    <button onClick={() => void commentAction(comment, "report")}>🚩</button>
                    <button onClick={() => setReplyTo(replyTo === comment.id ? null : comment.id)}>Reply</button>
                    {comment.heartedByCreator ? <span className="text-brand">❤️ creator hearted</span> : null}
                    {(isOwner || video.channel.ownerUserId === user?.id || user?.role === "admin") ? (
                      <>
                        <button onClick={() => void commentAction(comment, "pin")}>📌 Pin</button>
                        <button onClick={() => void commentAction(comment, "heart")}>❤️ Heart</button>
                        <button onClick={() => void commentAction(comment, "delete")}>🗑️ Remove</button>
                      </>
                    ) : null}
                  </div>

                  {replyTo === comment.id ? (
                    <div className="mt-2 flex gap-2">
                      <input id={`reply-${comment.id}`} placeholder="Add a reply..." className="flex-1 border-b border-line bg-transparent pb-1 text-sm outline-none focus:border-brand" />
                      <Button size="sm" onClick={() => void postComment(comment.id)}>Reply</Button>
                    </div>
                  ) : null}

                  {comment.replies?.length ? (
                    <div className="mt-3 space-y-4 border-l border-line pl-4">
                      {comment.replies.map((reply) => (
                        <div key={reply.id} className="flex gap-3">
                          <Avatar name={reply.author.name} src={reply.author.avatarUrl} size={28} />
                          <div className="min-w-0">
                            <p className="text-xs text-muted">
                              <span className="font-semibold text-fg">@{reply.author.handle}</span> · {timeAgo(reply.createdAt)}
                            </p>
                            <p className="text-sm">{reply.body}</p>
                            <button onClick={() => void commentAction(reply, "like")} className="mt-1 text-xs text-muted">
                              👍 {formatCount(reply.likeCount)}
                            </button>
                          </div>
                        </div>
                      ))}
                    </div>
                  ) : null}
                </div>
              </div>
            ))}
          </div>
        </section>
      </div>

      {/* sidebar */}
      <aside className="w-full shrink-0 space-y-4 xl:w-[402px]">
        {playlist ? (
          <div className="rounded-xl border border-line">
            <div className="border-b border-line p-3">
              <p className="text-sm font-semibold">{playlist.playlist.title}</p>
              <p className="text-xs text-muted">
                {playlist.playlist.itemCount} videos · {user ? "your playlist" : "playlist"}
              </p>
            </div>
            <div className="max-h-80 space-y-2 overflow-y-auto p-2">
              {playlist.items.map((item) => (
                <div key={item.id} className={`rounded-lg p-1 ${item.id === video.id ? "bg-brand/10" : ""}`}>
                  <VideoCard video={item} layout="row" showChannel={false} />
                </div>
              ))}
            </div>
          </div>
        ) : null}

        <div className="flex gap-2 overflow-x-auto no-scrollbar">
          {["All", "From this channel", "Related", "Recently uploaded", "Watched"].map((label) => (
            <span key={label} className="shrink-0 rounded-lg bg-chip px-3 py-1 text-xs font-medium">
              {label}
            </span>
          ))}
        </div>

        <div className="space-y-4">
          {related.map((item) => (
            <VideoCard key={item.id} video={item} layout="row" />
          ))}
        </div>
      </aside>

      <Modal open={reportOpen} onClose={() => setReportOpen(false)} title="Report video">
        <div className="space-y-1">
          {REPORT_REASONS.map((reason) => (
            <button
              key={reason.value}
              onClick={async () => {
                await api(`/api/videos/${video.id}/report`, { method: "POST", json: { targetType: "video", targetId: video.id, reason: reason.value } }).catch((e) => toast(e.message));
                toast("Report submitted");
                setReportOpen(false);
              }}
              className="w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-surface"
            >
              {reason.label}
            </button>
          ))}
        </div>
      </Modal>

      <Modal open={saveOpen} onClose={() => setSaveOpen(false)} title="Save to playlist">
        <div className="space-y-1">
          {playlists.map((playlist) => (
            <button key={playlist.id} onClick={() => void saveTo(playlist.id)} className="w-full rounded-lg px-3 py-2 text-left text-sm hover:bg-surface">
              {playlist.title}
            </button>
          ))}
        </div>
      </Modal>

      <Modal open={memberOpen} onClose={() => setMemberOpen(false)} title={`Join ${video.channel.name}`}>
        <p className="text-sm text-muted">
          Members get badges, exclusive uploads and early access. Cancel any time.
        </p>
        <Button className="mt-4 w-full" onClick={() => void joinMembership()}>
          Join for $4.99 / month
        </Button>
      </Modal>

      <Modal open={thanksOpen} onClose={() => setThanksOpen(false)} title="Say thanks">
        <div className="grid grid-cols-3 gap-2">
          {[200, 500, 1000].map((amount) => (
            <button key={amount} onClick={() => void sendThanks(amount)} className="rounded-xl border border-line p-4 text-center hover:bg-surface">
              <p className="text-lg font-bold text-brand">${(amount / 100).toFixed(2)}</p>
              <p className="text-xs text-muted">Super Thanks</p>
            </button>
          ))}
        </div>
      </Modal>

      {gate ? (
        <div className="fixed inset-0 z-[110] grid place-items-center bg-black/90 p-6 text-center">
          <div className="max-w-sm">
            <p className="text-4xl">🔞</p>
            <h2 className="mt-3 text-xl font-bold text-white">This video is age restricted</h2>
            <p className="mt-2 text-sm text-white/70">
              It may contain content unsuitable for viewers under 18. Parental controls are available in Settings.
            </p>
            <button
              onClick={() => {
                try {
                  localStorage.setItem("playtube-adult", "1");
                } catch {}
                setAgeOk(true);
              }}
              className="mt-4 rounded-full bg-brand px-5 py-2 font-semibold text-white"
            >
              I am over 18
            </button>
          </div>
        </div>
      ) : null}
      {toastNode}
    </div>
  );
}
