"use client";

import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import Hls from "hls.js";
import { Avatar, Button, useToast } from "@/components/ui";
import { useSession } from "@/components/session-provider";
import { api } from "@/lib/api-client";
import { formatCount } from "@/lib/format";
import type { LiveStream } from "@/db/schema";

type ChatMessage = {
  id: number;
  message: string;
  amountCents: number;
  isSuperChat: boolean;
  createdAt: string;
  author: { id: string; name: string; handle: string; avatarUrl: string | null };
};

export function LiveWatch({
  stream,
  channel,
  initialMessages,
  isOwner,
  signedIn,
}: {
  stream: LiveStream;
  channel: { name: string; handle: string; avatarUrl: string | null; subscriberCountHint: boolean };
  initialMessages: ChatMessage[];
  isOwner: boolean;
  signedIn: boolean;
}) {
  const { user } = useSession();
  const { toast, toastNode } = useToast();
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const [messages, setMessages] = useState(initialMessages);
  const [text, setText] = useState("");
  const [viewers, setViewers] = useState(stream.currentViewers);
  const [superChat, setSuperChat] = useState(false);
  const [amount, setAmount] = useState(500);
  const [status, setStatus] = useState(stream.status);

  useEffect(() => {
    const el = videoRef.current;
    const url = stream.playbackUrl;
    if (!el || !url) return;
    if (url.includes(".m3u8") && Hls.isSupported()) {
      const hls = new Hls({ liveDurationInfinity: true, lowLatencyMode: true });
      hls.loadSource(url);
      hls.attachMedia(el);
      return () => hls.destroy();
    }
    el.src = url;
  }, [stream.playbackUrl]);

  useEffect(() => {
    const source = new EventSource(`/api/realtime?stream=${stream.id}`);
    source.onmessage = (event) => {
      try {
        const payload = JSON.parse(event.data) as {
          kind: string;
          message?: ChatMessage;
          viewers?: number;
        };
        if (payload.kind === "live-chat" && payload.message) {
          setMessages((prev) => [...prev, payload.message!].slice(-150));
        }
        if (payload.kind === "live-viewers" && typeof payload.viewers === "number") {
          setViewers(payload.viewers);
        }
      } catch {
        /* ignore */
      }
    };
    return () => source.close();
  }, [stream.id]);

  useEffect(() => {
    const ping = setInterval(() => {
      void api<{ viewers: number }>(`/api/live/${stream.id}`, { method: "POST", json: { action: "viewer" } })
        .then((data) => setViewers(data.viewers))
        .catch(() => undefined);
    }, 30_000);
    return () => clearInterval(ping);
  }, [stream.id]);

  const send = async (isSuper = false) => {
    if (!user) return toast("Sign in to chat");
    if (!text.trim()) return;
    await api(`/api/live/${stream.id}`, {
      method: "POST",
      json: { action: isSuper ? "super-chat" : "chat", message: text, amountCents: isSuper ? amount : undefined },
    }).catch((e) => toast(e.message));
    setText("");
    setSuperChat(false);
  };

  const moderate = async (messageId: number) => {
    await api(`/api/live/${stream.id}`, { method: "POST", json: { action: "moderate", messageId } }).catch((e) => toast(e.message));
    setMessages((prev) => prev.filter((m) => m.id !== messageId));
    toast("Message removed");
  };

  const control = async (action: "start" | "end") => {
    const data = await api<{ stream: LiveStream }>(`/api/live/${stream.id}`, { method: "POST", json: { action } }).catch((e) => {
      toast(e.message);
      return null;
    });
    if (data) {
      setStatus(data.stream.status);
      toast(action === "start" ? "Stream started" : "Stream ended — replay available");
    }
  };

  return (
    <div className="flex flex-col gap-4 px-2 py-3 sm:px-6 lg:flex-row">
      <div className="min-w-0 flex-1">
        <div className="relative aspect-video w-full overflow-hidden rounded-xl bg-black">
          <video ref={videoRef} controls playsInline poster={stream.thumbnailUrl ?? undefined} className="h-full w-full object-contain" />
          {status !== "live" ? (
            <div className="absolute inset-0 grid place-items-center bg-black/80 text-center text-white">
              <div>
                <p className="text-lg font-bold">{status === "scheduled" ? "Stream has not started yet" : "This stream has ended"}</p>
                <p className="text-sm text-white/70">Peak viewers: {formatCount(stream.peakViewers)}</p>
                {isOwner && status === "scheduled" ? (
                  <Button className="mt-3" onClick={() => void control("start")}>Start streaming</Button>
                ) : null}
              </div>
            </div>
          ) : null}
        </div>

        <h1 className="mt-3 text-lg font-bold">{stream.title}</h1>
        <div className="mt-2 flex flex-wrap items-center gap-3">
          <Link href={`/channel/${channel.handle}`} className="flex items-center gap-3">
            <Avatar name={channel.name} src={channel.avatarUrl} size={40} />
            <div>
              <p className="text-sm font-semibold">{channel.name}</p>
              <p className="text-xs text-muted">🔴 {formatCount(viewers)} watching now</p>
            </div>
          </Link>
          <Button
            onClick={() =>
              void api(`/api/channels/${channel.handle}`, { method: "POST" }).then(() => toast("Subscribed")).catch((e) => toast(e.message))
            }
          >
            Subscribe
          </Button>
          {isOwner ? (
            <>
              {status === "live" ? <Button variant="danger" onClick={() => void control("end")}>End stream</Button> : null}
              <span className="rounded-lg bg-chip px-3 py-2 font-mono text-xs">key: {stream.streamKey}</span>
            </>
          ) : null}
        </div>
        <p className="mt-3 whitespace-pre-line text-sm text-muted">{stream.description}</p>
      </div>

      <aside className="flex h-[60vh] w-full flex-col rounded-xl border border-line lg:h-[calc(100dvh-6rem)] lg:w-96">
        <div className="flex items-center justify-between border-b border-line px-4 py-3">
          <h2 className="text-sm font-bold">Live chat</h2>
          <span className="text-xs text-muted">{formatCount(viewers)} viewers</span>
        </div>
        <div className="flex-1 space-y-3 overflow-y-auto p-3">
          {messages.length === 0 ? <p className="text-xs text-muted">Say hi to start the conversation.</p> : null}
          {messages.map((message) => (
            <div key={message.id} className={`flex gap-2 rounded-lg p-2 ${message.isSuperChat ? "bg-brand/15" : ""}`}>
              <Avatar name={message.author.name} src={message.author.avatarUrl} size={26} />
              <div className="min-w-0 flex-1">
                <p className="text-xs">
                  <span className="font-semibold">{message.author.name}</span>{" "}
                  <span className="text-muted">{message.isSuperChat ? `· Super Chat $${(message.amountCents / 100).toFixed(2)}` : ""}</span>
                </p>
                <p className="break-words text-sm">{message.message}</p>
              </div>
              {isOwner ? (
                <button onClick={() => void moderate(message.id)} className="text-xs text-muted hover:text-brand">
                  ✕
                </button>
              ) : null}
            </div>
          ))}
        </div>
        <div className="border-t border-line p-3">
          {superChat ? (
            <div className="mb-2 space-y-2 rounded-lg bg-surface p-2">
              <div className="flex gap-2">
                {[200, 500, 1000, 2000].map((value) => (
                  <button key={value} onClick={() => setAmount(value)} className={`flex-1 rounded px-2 py-1 text-xs font-semibold ${amount === value ? "bg-brand text-white" : "bg-chip"}`}>
                    ${(value / 100).toFixed(0)}
                  </button>
                ))}
              </div>
              <p className="text-[11px] text-muted">Super Chat highlights your message for the creator.</p>
            </div>
          ) : null}
          <div className="flex gap-2">
            <input
              value={text}
              onChange={(event) => setText(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === "Enter") void send(superChat);
              }}
              placeholder={signedIn ? "Chat publicly..." : "Sign in to chat"}
              disabled={!signedIn}
              className="flex-1 rounded-full border border-line bg-surface px-3 py-2 text-sm"
            />
            <Button size="sm" variant="secondary" onClick={() => setSuperChat((v) => !v)}>💰</Button>
            <Button size="sm" onClick={() => void send(superChat)} disabled={!signedIn}>Send</Button>
          </div>
        </div>
      </aside>
      {toastNode}
    </div>
  );
}
