import { useCallback, useEffect, useState } from "react";
import {
  X,
  Heart,
  MessageCircle,
  Eye,
  Send,
  Loader2,
  Pin,
} from "lucide-react";
import { api } from "@/client";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
  type ArticleDetail as ArticleDetailType,
  type ArticleComment,
  articleColor,
  articleInitial,
  formatRelativeTime,
  formatCount,
} from "./article-types";

type Props = {
  article: ArticleDetailType;
  currentUserId?: string;
  onClose: () => void;
  onUpdated: (article: ArticleDetailType) => void;
};

export default function ArticleDetail({
  article: initialArticle,
  currentUserId,
  onClose,
  onUpdated,
}: Props) {
  const [article, setArticle] = useState(initialArticle);
  const [liked, setLiked] = useState(false);
  const [liking, setLiking] = useState(false);
  const [comments, setComments] = useState<ArticleComment[]>([]);
  const [loadingComments, setLoadingComments] = useState(true);
  const [commentText, setCommentText] = useState("");
  const [sendingComment, setSendingComment] = useState(false);

  // Load comments
  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect -- fetch on mount
    setLoadingComments(true);
    api
      .get<Record<string, unknown>>(
        `/api/v1/ws/articles/${article.id}/comments`,
        { params: { limit: 50 } },
      )
      .then((res) => {
        const data = res.data as Record<string, unknown>;
        setComments((data.comments ?? []) as ArticleComment[]);
      })
      .catch(() => {})
      .finally(() => setLoadingComments(false));
  }, [article.id]);

  // Group comments by parent
  const commentTree = useCallback(() => {
    const root: ArticleComment[] = [];
    const children = new Map<string, ArticleComment[]>();
    for (const c of comments) {
      if (c.parent) {
        const arr = children.get(c.parent) ?? [];
        arr.push(c);
        children.set(c.parent, arr);
      } else {
        root.push(c);
      }
    }
    return { root, children };
  }, [comments]);

  const handleLike = useCallback(async () => {
    if (liking) return;
    setLiking(true);
    try {
      const nextLiked = !liked;
      await api.post(`/api/v1/ws/articles/${article.id}/like`, {
        like: nextLiked,
      });
      setLiked(nextLiked);
      const newCount = nextLiked ? article.like_count + 1 : Math.max(0, article.like_count - 1);
      const updated = { ...article, like_count: newCount };
      setArticle(updated);
      onUpdated(updated);
    } catch {
      // ignore
    } finally {
      setLiking(false);
    }
  }, [liked, liking, article, onUpdated]);

  const handleSendComment = useCallback(async () => {
    const trimmed = commentText.trim();
    if (!trimmed || sendingComment) return;
    setSendingComment(true);
    try {
      await api.post(`/api/v1/ws/articles/${article.id}/comments`, {
        content: trimmed,
      });
      setCommentText("");
      // Reload comments
      const res = await api.get<Record<string, unknown>>(
        `/api/v1/ws/articles/${article.id}/comments`,
        { params: { limit: 50 } },
      );
      const data = res.data as Record<string, unknown>;
      setComments((data.comments ?? []) as ArticleComment[]);
      const updated = { ...article, comment_count: article.comment_count + 1 };
      setArticle(updated);
      onUpdated(updated);
    } catch {
      // ignore
    } finally {
      setSendingComment(false);
    }
  }, [commentText, sendingComment, article, onUpdated]);

  const handleDeleteComment = useCallback(
    async (commentId: string) => {
      try {
        await api.delete(
          `/api/v1/ws/articles/${article.id}/comments/${commentId}`,
        );
        setComments((prev) => prev.filter((c) => c.id !== commentId));
        const updated = {
          ...article,
          comment_count: Math.max(0, article.comment_count - 1),
        };
        setArticle(updated);
        onUpdated(updated);
      } catch {
        // ignore
      }
    },
    [article, onUpdated],
  );

  const authorName =
    article.author.display_name || article.author.username || "Anonymous";
  const color = articleColor(authorName);
  const initial = articleInitial(authorName);
  const { root, children } = commentTree();

  return (
    <div className="flex min-h-full flex-col">
      {/* Header */}
      <div className="flex shrink-0 items-center gap-3 border-b border-border/40 px-5 py-3">
        <Button
          className="size-8 shrink-0 cursor-pointer rounded-lg"
          onClick={onClose}
          size="icon"
          variant="ghost"
        >
          <X className="size-4" />
        </Button>
        <div className="min-w-0 flex-1">
          <h2 className="truncate text-sm font-semibold">Article Detail</h2>
        </div>
        {article.is_pinned && (
          <span className="inline-flex items-center gap-1 rounded-full bg-warning/10 px-2 py-0.5 text-[11px] font-medium text-warning/70">
            <Pin className="size-3" />
            Pinned
          </span>
        )}
      </div>

      <div className="min-h-0 flex-1 overflow-y-auto">
        {/* Cover */}
        {article.cover_url && (
          <div className="aspect-[2/1] w-full overflow-hidden bg-muted/20">
            <img
              alt={article.title}
              className="size-full object-cover"
              src={article.cover_url}
            />
          </div>
        )}

        <div className="px-5 py-4">
          {/* Title */}
          <h1 className="text-xl font-bold leading-snug">{article.title}</h1>

          {/* Author + meta */}
          <div className="mt-3 flex items-center gap-3">
            {article.author.avatar_url ? (
              <img
                alt={authorName}
                className="size-9 shrink-0 rounded-full object-cover ring-2 ring-border/20"
                src={article.author.avatar_url}
              />
            ) : (
              <div
                className={cn(
                  "grid size-9 shrink-0 place-items-center rounded-full bg-gradient-to-br text-sm font-bold text-white ring-2 ring-border/20",
                  color,
                )}
              >
                {initial}
              </div>
            )}
            <div className="min-w-0 flex-1">
              <p className="text-sm font-semibold">{authorName}</p>
              <p className="text-[12px] text-muted-foreground/50">
                {formatRelativeTime(article.created_at)}
                {article.updated_at !== article.created_at && " ((edited))"}
              </p>
            </div>
          </div>

          {/* Tags */}
          {article.tags.length > 0 && (
            <div className="mt-3 flex flex-wrap gap-1.5">
              {article.tags.map((tag) => (
                <span
                  className="rounded-md bg-primary/[0.06] px-2 py-0.5 text-[11px] font-medium text-primary/60"
                  key={tag}
                >
                  {tag}
                </span>
              ))}
            </div>
          )}

          {/* Content */}
          <div className="prose prose-sm mt-6 max-w-none prose-p:leading-relaxed prose-a:text-primary/70 prose-img:rounded-xl">
            {article.content.split("\n").map((line, i) => (
              <p key={i}>{line || "\u00A0"}</p>
            ))}
          </div>

          {/* Stats bar */}
          <div className="mt-6 flex items-center gap-4 border-t border-border/30 pt-4 text-[13px] text-muted-foreground/50">
            <span className="inline-flex items-center gap-1">
              <Eye className="size-4" />
              {formatCount(article.view_count)}  views
            </span>
            <span className="inline-flex items-center gap-1">
              <MessageCircle className="size-4" />
              {formatCount(article.comment_count)}  comments
            </span>
          </div>

          {/* Like button */}
          <div className="mt-4 flex justify-center">
            <button
              className={cn(
                "inline-flex cursor-pointer items-center gap-2 rounded-full px-5 py-2.5 text-sm font-medium transition-[background-color,border-color,color,opacity,box-shadow,transform] duration-200",
                liked
                  ? "bg-rose-500/10 text-rose-500 ring-1 ring-rose-500/20"
                  : "bg-muted/50 text-muted-foreground/60 hover:bg-rose-500/[0.04] hover:text-rose-500/70",
              )}
              disabled={liking}
              onClick={handleLike}
              type="button"
            >
              <Heart
                className={cn(
                  "size-[18px] transition-[fill,color,transform]",
                  liked && "fill-rose-500",
                )}
              />
              {liked ? "Liked" : "Like"}
              <span className="tabular-nums">
                {formatCount(article.like_count)}
              </span>
            </button>
          </div>
        </div>

        {/* Comments */}
        <div className="border-t border-border/30 px-5 py-4">
          <h3 className="mb-4 text-sm font-semibold">
             comments ({article.comment_count})
          </h3>

          {loadingComments ? (
            <div className="flex justify-center py-8">
              <Loader2 className="size-4 animate-spin text-muted-foreground/20" />
            </div>
          ) : root.length === 0 ? (
            <p className="py-8 text-center text-[13px] text-muted-foreground/35">
              No comments yet. Be the first.
            </p>
          ) : (
            <div className="space-y-4">
              {root.map((comment) => (
                <CommentItem
                  articleAuthorId={article.author.id}
                  children={children}
                  comment={comment}
                  currentUserId={currentUserId}
                  key={comment.id}
                  onDelete={handleDeleteComment}
                />
              ))}
            </div>
          )}

          {/* Comment composer */}
          <div className="mt-4 flex items-end gap-2">
            <textarea
              className="min-h-[40px] max-h-32 flex-1 resize-none rounded-xl border border-border/40 bg-muted/30 px-3 py-2.5 text-sm placeholder:text-muted-foreground/30 focus:border-primary/20 focus:outline-none focus:ring-1 focus:ring-primary/[0.06]"
              onChange={(e) => setCommentText(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === "Enter" && !e.shiftKey) {
                  e.preventDefault();
                  handleSendComment();
                }
              }}
              placeholder="Write a comment..."
              rows={1}
              value={commentText}
            />
            <Button
              className="size-9 shrink-0 cursor-pointer rounded-xl"
              disabled={!commentText.trim() || sendingComment}
              onClick={handleSendComment}
              size="icon"
            >
              {sendingComment ? (
                <Loader2 className="size-4 animate-spin" />
              ) : (
                <Send className="size-[15px]" />
              )}
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
}

function CommentItem({
  comment,
  children,
  articleAuthorId,
  currentUserId,
  onDelete,
}: {
  comment: ArticleComment;
  children: Map<string, ArticleComment[]>;
  articleAuthorId: string;
  currentUserId?: string;
  onDelete: (id: string) => void;
}) {
  const replies = children.get(comment.id) ?? [];
  const canDelete =
    currentUserId === comment.author || currentUserId === articleAuthorId;

  return (
    <div className="group">
      <div className="flex gap-2.5">
        <div className="grid size-7 shrink-0 place-items-center rounded-full bg-muted/50 text-[10px] font-semibold text-muted-foreground/50">
          {comment.author.slice(0, 2).toUpperCase()}
        </div>
        <div className="min-w-0 flex-1">
          <div className="flex items-baseline gap-2">
            <span className="text-[13px] font-semibold">
              {comment.author.slice(0, 8)}
            </span>
            <span className="text-[10px] text-muted-foreground/35">
              {formatRelativeTime(comment.created_at)}
            </span>
          </div>
          <p className="mt-1 text-[13px] leading-relaxed text-foreground/80">
            {comment.content}
          </p>
          {canDelete && (
            <button
              className="mt-1 cursor-pointer text-[10px] text-muted-foreground/25 opacity-0 transition-opacity hover:text-destructive/60 group-hover:opacity-100"
              onClick={() => onDelete(comment.id)}
              type="button"
            >
              Delete
            </button>
          )}
        </div>
      </div>
      {replies.length > 0 && (
        <div className="ml-9 mt-2 space-y-3 border-l-2 border-border/20 pl-4">
          {replies.map((reply) => (
            <CommentItem
              articleAuthorId={articleAuthorId}
              children={children}
              comment={reply}
              currentUserId={currentUserId}
              key={reply.id}
              onDelete={onDelete}
            />
          ))}
        </div>
      )}
    </div>
  );
}
