"use client";

import Link from "next/link";
import { useState } from "react";
import { VideoCard, type VideoCardData } from "@/components/video-card";
import { Avatar, Button, useToast } from "@/components/ui";
import { useSession } from "@/components/session-provider";
import { api, uploadFile } from "@/lib/api-client";
import { formatCount, formatDate } from "@/lib/format";
import type { LiveStream, Playlist } from "@/db/schema";

type ChannelData = {
  id: string;
  name: string;
  handle: string;
  description: string | null;
  avatarUrl: string | null;
  bannerUrl: string | null;
  isVerified: boolean;
  isMonetized: boolean;
  memberPrice: number;
  memberPerks: string | null;
  country: string;
  links: { label: string; url: string }[] | null;
  keywords: string | null;
  trailerVideoId: string | null;
  subscriberCount: number;
  videoCount: number;
  totalViews: number;
  createdAt: string | Date;
  userId: string;
};

const TABS = ["home", "videos", "shorts", "live", "playlists", "community", "about"] as const;

export function ChannelView({
  channel,
  videos,
  shorts,
  streams,
  playlists,
  subscribed,
  notify,
  isOwner,
  initialTab,
}: {
  channel: ChannelData;
  videos: VideoCardData[];
  shorts: VideoCardData[];
  streams: LiveStream[];
  playlists: Playlist[];
  subscribed: boolean;
  notify: boolean;
  isOwner: boolean;
  initialTab: string;
}) {
  const { user } = useSession();
  const { toast, toastNode } = useToast();
  const [tab, setTab] = useState<(typeof TABS)[number]>(
    (TABS as readonly string[]).includes(initialTab) ? (initialTab as (typeof TABS)[number]) : "home",
  );
  const [isSubscribed, setIsSubscribed] = useState(subscribed);
  const [notifyAll, setNotifyAll] = useState(notify);
  const [subs, setSubs] = useState(channel.subscriberCount);
  const [posts, setPosts] = useState<
    {
      id: string;
      body: string;
      imageUrl: string | null;
      isAnnouncement: boolean;
      pollOptions: string[];
      likeCount: number;
      commentCount: number;
      liked: boolean;
      myVote: number | null;
      pollResults: { index: number; count: number }[];
      createdAt: string;
      comments: { id: string; body: string; authorName: string; authorAvatar: string | null }[];
    }[]
  >([]);
  const [newPost, setNewPost] = useState("");
  const [pollOptions, setPollOptions] = useState("");
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState({ name: channel.name, description: channel.description ?? "", keywords: channel.keywords ?? "" });

  const loadPosts = async () => {
    const data = await api<{ items: typeof posts }>(`/api/community?channel=${channel.handle}`).catch(() => null);
    if (data) setPosts(data.items);
  };

  const toggleSub = async () => {
    if (!user) return toast("Sign in to subscribe");
    const data = await api<{ subscribed: boolean; subscriberCount: number }>(`/api/channels/${channel.handle}`, { method: "POST" }).catch((e) => {
      toast(e.message);
      return null;
    });
    if (data) {
      setIsSubscribed(data.subscribed);
      setSubs(data.subscriberCount);
    }
  };

  const saveChannel = async () => {
    await api(`/api/channels/${channel.handle}`, { method: "PATCH", json: draft }).catch((e) => toast(e.message));
    toast("Channel updated");
    setEditing(false);
    window.location.reload();
  };

  const uploadImage = async (file: File, field: "avatarUrl" | "bannerUrl") => {
    try {
      const stored = await uploadFile(file, "image", `uploads/${field === "avatarUrl" ? "avatars" : "banners"}`);
      await api(`/api/channels/${channel.handle}`, { method: "PATCH", json: { [field]: stored.url } });
      toast("Updated");
      window.location.reload();
    } catch (error) {
      toast(error instanceof Error ? error.message : "Upload failed");
    }
  };

  const createPost = async () => {
    if (!user) return toast("Sign in first");
    await api("/api/community", {
      method: "POST",
      json: { body: newPost, pollOptions: pollOptions ? pollOptions.split("\n").map((s) => s.trim()).filter(Boolean).slice(0, 6) : [] },
    }).catch((e) => toast(e.message));
    setNewPost("");
    setPollOptions("");
    await loadPosts();
    toast("Posted");
  };

  const vote = async (postId: string, optionIndex: number) => {
    const data = await api<{ myVote: number; results: { index: number; count: number }[] }>(`/api/community/${postId}/vote`, {
      method: "POST",
      json: { optionIndex },
    }).catch((e) => {
      toast(e.message);
      return null;
    });
    if (data) {
      setPosts((prev) =>
        prev.map((post) => (post.id === postId ? { ...post, myVote: data.myVote, pollResults: data.results } : post)),
      );
    }
  };

  const likePost = async (postId: string) => {
    if (!user) return toast("Sign in first");
    const data = await api<{ liked: boolean; likeCount: number }>(`/api/community/${postId}/like`, { method: "POST" }).catch(() => null);
    if (data) {
      setPosts((prev) => prev.map((post) => (post.id === postId ? { ...post, liked: data.liked, likeCount: data.likeCount } : post)));
    }
  };

  return (
    <div>
      <div className="relative h-28 w-full overflow-hidden bg-gradient-to-r from-brand/40 to-surface sm:h-40 lg:h-52">
        {channel.bannerUrl ? (
          // eslint-disable-next-line @next/next/no-img-element
          <img src={channel.bannerUrl} alt="" className="h-full w-full object-cover" />
        ) : null}
        {isOwner ? (
          <label className="absolute bottom-3 right-3 cursor-pointer rounded-full bg-black/70 px-3 py-1.5 text-xs font-semibold text-white">
            Edit banner
            <input type="file" accept="image/*" hidden onChange={(event) => { const file = event.target.files?.[0]; if (file) void uploadImage(file, "bannerUrl"); }} />
          </label>
        ) : null}
      </div>

      <div className="flex flex-col gap-4 px-4 py-4 sm:flex-row sm:items-center">
        <label className="relative w-fit cursor-pointer">
          <Avatar name={channel.name} src={channel.avatarUrl} size={96} />
          {isOwner ? (
            <span className="absolute -bottom-1 -right-1 rounded-full bg-brand px-2 py-0.5 text-[10px] font-bold text-white">edit</span>
          ) : null}
          {isOwner ? (
            <input type="file" accept="image/*" hidden onChange={(event) => { const file = event.target.files?.[0]; if (file) void uploadImage(file, "avatarUrl"); }} />
          ) : null}
        </label>
        <div className="min-w-0 flex-1">
          <h1 className="flex items-center gap-2 text-xl font-bold sm:text-2xl">
            {channel.name}
            {channel.isVerified ? <span aria-label="verified">✔️</span> : null}
          </h1>
          <p className="text-sm text-muted">
            @{channel.handle} · {formatCount(subs)} subscribers · {formatCount(channel.videoCount)} videos ·{" "}
            {formatCount(channel.totalViews)} views
          </p>
          <p className="line-clamp-1 text-sm text-muted">{channel.description ?? "No description yet"}</p>
          <div className="mt-3 flex flex-wrap items-center gap-2">
            {!isOwner ? (
              <>
                <Button variant={isSubscribed ? "secondary" : "primary"} onClick={() => void toggleSub()}>
                  {isSubscribed ? "Subscribed" : "Subscribe"}
                </Button>
                {isSubscribed ? (
                  <button
                    onClick={async () => {
                      const data = await api<{ notify: boolean }>(`/api/channels/${channel.handle}?mode=notify`, {
                        method: "POST",
                        json: { notify: !notifyAll },
                      }).catch(() => null);
                      if (data) {
                        setNotifyAll(data.notify);
                        toast(data.notify ? "All notifications on" : "Notifications personalized");
                      }
                    }}
                    className="rounded-full bg-surface px-3 py-2 text-sm"
                  >
                    {notifyAll ? "🔔 All" : "🔕 Personalized"}
                  </button>
                ) : null}
                <Button variant="secondary" onClick={() => void api("/api/monetization", { method: "POST", json: { action: "join", channelId: channel.id } }).then(() => toast("Membership started")).catch((e) => toast(e.message))}>
                  💎 Join ${channel.memberPrice ? (channel.memberPrice / 100).toFixed(2) : "4.99"}
                </Button>
                <Button
                  variant="secondary"
                  onClick={async () => {
                    const url = `${window.location.origin}/channel/${channel.handle}`;
                    if (navigator.share) await navigator.share({ title: channel.name, url }).catch(() => undefined);
                    else {
                      await navigator.clipboard.writeText(url);
                      toast("Profile link copied");
                    }
                  }}
                >
                  ↗️ Share profile
                </Button>
                <Button
                  variant="secondary"
                  onClick={async () => {
                    if (!user) return toast("Sign in first");
                    await api("/api/me", { method: "POST", json: { action: "block", userId: channel.userId } }).catch((e) => toast(e.message));
                    toast("User blocked");
                  }}
                >
                  🚫 Block
                </Button>
              </>
            ) : (
              <>
                <Link href="/studio" className="rounded-full bg-surface px-4 py-2 text-sm font-semibold">Manage videos</Link>
                <Button variant="secondary" onClick={() => setEditing((v) => !v)}>Customise channel</Button>
              </>
            )}
          </div>
        </div>
      </div>

      {editing ? (
        <div className="mx-4 mb-4 space-y-3 rounded-xl border border-line p-4">
          <input value={draft.name} onChange={(event) => setDraft({ ...draft, name: event.target.value })} className="w-full rounded-lg border border-line bg-surface px-3 py-2 text-sm" placeholder="Channel name" />
          <textarea value={draft.description} onChange={(event) => setDraft({ ...draft, description: event.target.value })} rows={3} className="w-full rounded-lg border border-line bg-surface px-3 py-2 text-sm" placeholder="Description" />
          <input value={draft.keywords} onChange={(event) => setDraft({ ...draft, keywords: event.target.value })} className="w-full rounded-lg border border-line bg-surface px-3 py-2 text-sm" placeholder="Keywords (comma separated)" />
          <div className="flex gap-2">
            <Button size="sm" onClick={() => void saveChannel()}>Save</Button>
            <Button size="sm" variant="ghost" onClick={() => setEditing(false)}>Cancel</Button>
          </div>
        </div>
      ) : null}

      <div className="no-scrollbar sticky top-14 z-20 flex gap-6 overflow-x-auto border-b border-line bg-bg px-4">
        {TABS.map((item) => (
          <button
            key={item}
            onClick={() => {
              setTab(item);
              if (item === "community" && posts.length === 0) void loadPosts();
            }}
            className={`shrink-0 border-b-2 py-3 text-sm font-semibold capitalize transition ${
              tab === item ? "border-fg text-fg" : "border-transparent text-muted hover:text-fg"
            }`}
          >
            {item}
          </button>
        ))}
      </div>

      <div className="px-4 py-5">
        {tab === "home" ? (
          <div className="space-y-6">
            {channel.description ? (
              <p className="max-w-3xl whitespace-pre-line text-sm text-muted">{channel.description}</p>
            ) : null}
            <h2 className="text-base font-bold">Videos</h2>
            <div className="grid grid-cols-1 gap-x-4 gap-y-8 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4">
              {videos.slice(0, 8).map((video) => (
                <VideoCard key={video.id} video={video} />
              ))}
            </div>
            {videos.length > 8 ? (
              <Button variant="secondary" onClick={() => setTab("videos")}>View all videos</Button>
            ) : null}
          </div>
        ) : null}

        {tab === "videos" ? (
          <div className="space-y-4">
            {videos.length === 0 ? <p className="text-sm text-muted">No uploads yet.</p> : null}
            <div className="grid grid-cols-1 gap-x-4 gap-y-8 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4">
              {videos.map((video) => (
                <VideoCard key={video.id} video={video} showChannel={false} />
              ))}
            </div>
          </div>
        ) : null}

        {tab === "shorts" ? (
          <div className="no-scrollbar flex gap-4 overflow-x-auto">
            {shorts.length === 0 ? <p className="text-sm text-muted">No shorts yet.</p> : null}
            {shorts.map((short) => (
              <Link key={short.id} href="/shorts" className="w-36 shrink-0">
                <div className="aspect-[9/16] overflow-hidden rounded-xl bg-surface">
                  {short.thumbnailUrl ? (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={short.thumbnailUrl} alt="" className="h-full w-full object-cover" />
                  ) : null}
                </div>
                <p className="line-clamp-2 mt-2 text-xs font-semibold">{short.title}</p>
                <p className="text-[11px] text-muted">{formatCount(short.views)} views</p>
              </Link>
            ))}
          </div>
        ) : null}

        {tab === "live" ? (
          <div className="space-y-4">
            {streams.length === 0 ? <p className="text-sm text-muted">No live streams.</p> : null}
            {streams.map((stream) => (
              <Link key={stream.id} href={`/live/${stream.id}`} className="flex gap-3 rounded-xl p-2 hover:bg-surface">
                <div className="aspect-video w-48 shrink-0 overflow-hidden rounded-lg bg-surface">
                  {stream.thumbnailUrl ? (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={stream.thumbnailUrl} alt="" className="h-full w-full object-cover" />
                  ) : null}
                </div>
                <div>
                  <p className="font-semibold">{stream.title}</p>
                  <p className="text-xs text-muted">
                    {stream.status === "live" ? `🔴 Live · ${formatCount(stream.currentViewers)} watching` : stream.status === "scheduled" ? `Scheduled ${formatDate(stream.scheduledFor ?? stream.createdAt)}` : "Replay available"}
                  </p>
                  <p className="line-clamp-2 text-xs text-muted">{stream.description}</p>
                </div>
              </Link>
            ))}
          </div>
        ) : null}

        {tab === "playlists" ? (
          <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
            {playlists.length === 0 ? <p className="text-sm text-muted">No public playlists.</p> : null}
            {playlists.map((playlist) => (
              <Link key={playlist.id} href={`/playlist/${playlist.id}`} className="group">
                <div className="aspect-video overflow-hidden rounded-xl bg-surface">
                  {playlist.thumbnailUrl ? (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={playlist.thumbnailUrl} alt="" className="h-full w-full object-cover" />
                  ) : (
                    <div className="grid h-full place-items-center text-3xl">📁</div>
                  )}
                </div>
                <p className="mt-2 text-sm font-semibold">{playlist.title}</p>
                <p className="text-xs text-muted">{playlist.itemCount} videos</p>
              </Link>
            ))}
          </div>
        ) : null}

        {tab === "community" ? (
          <div className="max-w-2xl space-y-5">
            {isOwner ? (
              <div className="space-y-2 rounded-xl border border-line p-4">
                <textarea value={newPost} onChange={(event) => setNewPost(event.target.value)} rows={3} placeholder="Share something with your subscribers..." className="w-full rounded-lg border border-line bg-surface px-3 py-2 text-sm" />
                <textarea value={pollOptions} onChange={(event) => setPollOptions(event.target.value)} rows={2} placeholder={"Poll options (one per line, optional)"} className="w-full rounded-lg border border-line bg-surface px-3 py-2 text-sm" />
                <Button size="sm" onClick={() => void createPost()} disabled={!newPost.trim()}>Post</Button>
              </div>
            ) : null}
            {posts.map((post) => (
              <article key={post.id} className="rounded-xl border border-line p-4">
                <div className="flex items-center gap-3">
                  <Avatar name={channel.name} src={channel.avatarUrl} size={36} />
                  <div>
                    <p className="text-sm font-semibold">{channel.name}</p>
                    <p className="text-xs text-muted">{formatDate(post.createdAt)}</p>
                  </div>
                  {post.isAnnouncement ? <span className="ml-auto rounded bg-brand/15 px-2 py-0.5 text-[10px] font-bold text-brand">ANNOUNCEMENT</span> : null}
                </div>
                <p className="mt-3 whitespace-pre-line text-sm">{post.body}</p>
                {post.imageUrl ? (
                  // eslint-disable-next-line @next/next/no-img-element
                  <img src={post.imageUrl} alt="" className="mt-3 max-h-80 w-full rounded-lg object-cover" />
                ) : null}
                {post.pollOptions?.length ? (
                  <div className="mt-3 space-y-2">
                    {post.pollOptions.map((option, index) => {
                      const total = post.pollResults.reduce((sum, r) => sum + r.count, 0) || 1;
                      const count = post.pollResults.find((r) => r.index === index)?.count ?? 0;
                      return (
                        <button key={option} onClick={() => void vote(post.id, index)} className="relative w-full overflow-hidden rounded-lg border border-line px-3 py-2 text-left text-sm">
                          <span className="absolute inset-y-0 left-0 bg-brand/20" style={{ width: `${(count / total) * 100}%` }} />
                          <span className="relative flex justify-between">
                            <span>{option} {post.myVote === index ? "✓" : ""}</span>
                            <span className="text-muted">{Math.round((count / total) * 100)}%</span>
                          </span>
                        </button>
                      );
                    })}
                  </div>
                ) : null}
                <div className="mt-3 flex items-center gap-4 text-xs text-muted">
                  <button onClick={() => void likePost(post.id)} className={post.liked ? "font-bold text-brand" : ""}>
                    👍 {formatCount(post.likeCount)}
                  </button>
                  <span>💬 {formatCount(post.commentCount)}</span>
                </div>
                {post.comments?.length ? (
                  <div className="mt-3 space-y-2 border-t border-line pt-3">
                    {post.comments.map((comment) => (
                      <div key={comment.id} className="flex gap-2 text-sm">
                        <Avatar name={comment.authorName} src={comment.authorAvatar} size={24} />
                        <p><span className="font-semibold">{comment.authorName}</span> {comment.body}</p>
                      </div>
                    ))}
                  </div>
                ) : null}
              </article>
            ))}
            {posts.length === 0 ? <p className="text-sm text-muted">No community posts yet.</p> : null}
          </div>
        ) : null}

        {tab === "about" ? (
          <div className="max-w-2xl space-y-4 text-sm">
            <div>
              <h2 className="font-bold">Description</h2>
              <p className="mt-1 whitespace-pre-line text-muted">{channel.description ?? "—"}</p>
            </div>
            <div className="grid grid-cols-2 gap-4">
              <div><p className="font-semibold">Joined</p><p className="text-muted">{formatDate(channel.createdAt)}</p></div>
              <div><p className="font-semibold">Country</p><p className="text-muted">{channel.country}</p></div>
              <div><p className="font-semibold">Total views</p><p className="text-muted">{formatCount(channel.totalViews)}</p></div>
              <div><p className="font-semibold">Subscribers</p><p className="text-muted">{formatCount(subs)}</p></div>
            </div>
            {channel.links?.length ? (
              <div>
                <h2 className="font-bold">Links</h2>
                <ul className="mt-1 space-y-1">
                  {channel.links.map((link) => (
                    <li key={link.url}>
                      <a href={link.url} target="_blank" rel="noopener noreferrer" className="text-brand">{link.label}</a>
                    </li>
                  ))}
                </ul>
              </div>
            ) : null}
            {channel.memberPerks ? (
              <div>
                <h2 className="font-bold">Membership perks</h2>
                <p className="mt-1 text-muted">{channel.memberPerks}</p>
              </div>
            ) : null}
          </div>
        ) : null}
      </div>
      {toastNode}
    </div>
  );
}
