"use client";

import {
  useEffect,
  useRef,
  useState,
  useCallback,
  KeyboardEvent,
} from "react";
import { createPortal } from "react-dom";
import Image from "next/image";
import { MessageCircle, Send, X, ChevronDown, CornerDownRight, Pencil, Trash2, Check } from "lucide-react";
import Cookies from "js-cookie";
import { useAppDispatch, useAppSelector } from "@/store/hooks";
import { useRequireAuth } from "@/hooks/useRequireAuth";
import {
  fetchComments,
  submitComment,
  addOptimistic,
  fetchReplies,
  deleteComment,
  editComment,
} from "@/store/slices/commentSlice";
import { CommentItem } from "@/services/commentService";
import { useInfiniteScroll } from "@/hooks/useInfiniteScroll";
import { useTranslation } from "@/i18n";

/* ── helpers ──────────────────────────────────────────────────────────────── */

function makeKey(ct: number, cid: string) {
  return `${ct}-${cid}`;
}

function Avatar({
  src,
  name,
  size = 32,
}: {
  src: string;
  name: string;
  size?: number;
}) {
  const initials = (name || "U")[0].toUpperCase();
  return (
    <div
      className="relative rounded-full overflow-hidden flex-shrink-0 flex items-center justify-center font-bold"
      style={{ width: size, height: size, background: "var(--deep)", fontSize: size * 0.38, color: "var(--text-primary)" }}
    >
      {src ? (
        <Image src={src} alt={name} fill className="object-cover" unoptimized sizes={`${size}px`} />
      ) : (
        <span>{initials}</span>
      )}
    </div>
  );
}

/* ── Single comment row ───────────────────────────────────────────────────── */

function CommentRow({
  comment,
  contentType,
  contentId,
  episodeId,
  isReply = false,
}: {
  comment: CommentItem;
  contentType: number;
  contentId: string;
  episodeId: number;
  isReply?: boolean;
}) {
  const dispatch = useAppDispatch();
  const key = makeKey(contentType, contentId);
  const entry = useAppSelector((s) => s.comments.entries[key]);
  const myUserId = Cookies.get("user_id") ?? "";
  const isOwn = !!myUserId && comment.userId === myUserId;
  const requireAuth = useRequireAuth();
  const { t } = useTranslation();

  const [showReplyInput, setShowReplyInput] = useState(false);
  const [replyText, setReplyText] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [showReplies, setShowReplies] = useState(false);
  const [isEditing, setIsEditing] = useState(false);
  const [editText, setEditText] = useState(comment.comment);
  const [savingEdit, setSavingEdit] = useState(false);
  const [deleting, setDeleting] = useState(false);

  // Replies stored in the same slice with parentId = comment.id
  const replies = (entry?.comments ?? []).filter((c) => c.parentId === comment.id);

  const handleToggleReplies = () => {
    const next = !showReplies;
    setShowReplies(next);
    if (next && replies.length === 0) {
      // Fetch from API the first time
      dispatch(fetchReplies({ commentId: comment.id, key }));
    }
  };

  const handleSaveEdit = async () => {
    if (!editText.trim() || savingEdit) return;
    setSavingEdit(true);
    await dispatch(editComment({ commentId: comment.id, comment: editText.trim(), key }));
    setSavingEdit(false);
    setIsEditing(false);
  };

  const handleDelete = async () => {
    setDeleting(true);
    await dispatch(deleteComment({ commentId: comment.id, key }));
    setDeleting(false);
  };

  const handleSubmitReply = async () => {
    if (!replyText.trim() || submitting) return;
    setSubmitting(true);
    const optimisticId = `opt-reply-${Date.now()}`;
    dispatch(
      addOptimistic({
        key,
        comment: {
          id: optimisticId,
          parentId: comment.id,
          userId: "me",
          channelName: "You",
          avatar: "",
          comment: replyText.trim(),
          createdAt: "just now",
          isReply: true,
          totalReply: 0,
          isOptimistic: true,
        },
      }),
    );
    await dispatch(
      submitComment({
        contentType,
        contentId,
        comment: replyText.trim(),
        commentId: parseInt(comment.id),
        episodeId,
        optimisticId,
      }),
    );
    setReplyText("");
    setShowReplyInput(false);
    setShowReplies(true);
    setSubmitting(false);
  };

  return (
    <div className={isReply ? "pl-10" : ""}>
      <div
        className="flex items-start gap-2.5 py-3"
        style={{ opacity: comment.isOptimistic ? 0.65 : 1 }}
      >
        <Avatar src={comment.avatar} name={comment.channelName} size={isReply ? 28 : 34} />

        <div className="flex-1 min-w-0">
          {/* Header */}
          <div className="flex items-baseline gap-2 flex-wrap mb-1">
            <span className="text-[12px] font-bold leading-tight" style={{ color: "var(--text-primary)" }}>
              {comment.channelName}
            </span>
            <span className="text-[10px]" style={{ color: "var(--text-muted)" }}>
              {comment.createdAt}
            </span>
            {comment.isOptimistic && (
              <span className="text-[9px]" style={{ color: "var(--text-muted)" }}>{t("comment_posting")}</span>
            )}
          </div>

          {/* Text or edit textarea */}
          {isEditing ? (
            <div className="mt-1">
              <textarea
                className="w-full bg-transparent outline-none text-[12px] rounded-xl px-3 py-2 resize-none"
                style={{ border: "1px solid rgba(var(--accent-rgb),0.4)", minHeight: 60, background: "var(--btn-ghost)", color: "var(--text-primary)" }}
                value={editText}
                onChange={(e) => setEditText(e.target.value)}
                autoFocus
              />
              <div className="flex items-center gap-2 mt-1.5">
                <button
                  onClick={handleSaveEdit}
                  disabled={!editText.trim() || savingEdit}
                  className="flex items-center gap-1 text-[10px] font-bold px-2.5 py-1 rounded-full active:scale-95 disabled:opacity-40"
                  style={{ background: "rgba(var(--accent-rgb),0.15)", color: "var(--accent)" }}
                >
                  <Check size={10} strokeWidth={2.5} />
                  {savingEdit ? t("comment_saving") : t("feeds_save")}
                </button>
                <button
                  onClick={() => { setIsEditing(false); setEditText(comment.comment); }}
                  className="text-[10px] font-semibold px-2.5 py-1 rounded-full"
                  style={{ color: "var(--text-muted)" }}
                >
                  {t("common_cancel")}
                </button>
              </div>
            </div>
          ) : (
            <p className="text-[12px] leading-relaxed break-words" style={{ color: "var(--text-primary)", opacity: deleting ? 0.4 : 1 }}>
              {comment.comment}
            </p>
          )}

          {/* Actions */}
          {!comment.isOptimistic && !isEditing && (
            <div className="flex items-center gap-3 mt-1.5">
              {!isReply && (
                <button
                  className="flex items-center gap-1 text-[11px] font-semibold transition-colors"
                  style={{ color: showReplyInput ? "var(--accent)" : "var(--text-muted)" }}
                  onClick={() => requireAuth(() => setShowReplyInput((v) => !v))}
                >
                  <CornerDownRight size={11} strokeWidth={2} />
                  {t("feeds_reply")}
                </button>
              )}
              {comment.totalReply > 0 && !isReply && (
                <button
                  className="flex items-center gap-1 text-[11px] font-semibold transition-colors"
                  style={{ color: "var(--accent)" }}
                  onClick={handleToggleReplies}
                >
                  <ChevronDown
                    size={12}
                    strokeWidth={2}
                    style={{ transform: showReplies ? "rotate(180deg)" : "none", transition: "transform 0.2s" }}
                  />
                  {showReplies ? t("feeds_hide") : `${comment.totalReply} ${comment.totalReply === 1 ? t("comment_reply") : t("comment_replies")}`}
                </button>
              )}
              {isOwn && (
                <>
                  <button
                    className="flex items-center gap-1 text-[11px] transition-colors"
                    style={{ color: "var(--text-muted)" }}
                    onClick={() => setIsEditing(true)}
                    title="Edit comment"
                  >
                    <Pencil size={10} strokeWidth={2} />
                    {t("feeds_edit")}
                  </button>
                  <button
                    className="flex items-center gap-1 text-[11px] transition-colors"
                    style={{ color: deleting ? "#f43f5e" : "var(--text-muted)" }}
                    onClick={handleDelete}
                    disabled={deleting}
                    title="Delete comment"
                  >
                    <Trash2 size={10} strokeWidth={2} />
                    {deleting ? "…" : t("feeds_delete")}
                  </button>
                </>
              )}
            </div>
          )}

          {/* Inline reply input */}
          {showReplyInput && (
            <div className="flex items-center gap-2 mt-2.5">
              <Avatar src="" name="You" size={24} />
              <div
                className="flex-1 flex items-center gap-2 px-3 py-1.5 rounded-full"
                style={{ background: "var(--btn-ghost)", border: "1px solid var(--border)" }}
              >
                <input
                  className="flex-1 bg-transparent outline-none text-[11px]"
                  style={{ color: "var(--text-primary)" }}
                  placeholder={`${t("comment_replyTo")} ${comment.channelName}…`}
                  value={replyText}
                  onChange={(e) => setReplyText(e.target.value)}
                  onKeyDown={(e: KeyboardEvent<HTMLInputElement>) => {
                    if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); handleSubmitReply(); }
                  }}
                  autoFocus
                />
                <button
                  onClick={handleSubmitReply}
                  disabled={!replyText.trim() || submitting}
                  className="transition-all active:scale-90 disabled:opacity-40"
                >
                  <Send size={13} style={{ color: replyText.trim() ? "var(--accent)" : "#555" }} strokeWidth={2} />
                </button>
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Inline replies */}
      {showReplies && replies.length > 0 && (
        <div style={{ borderLeft: "1px solid var(--border)", marginLeft: 17 }}>
          {replies.map((r) => (
            <CommentRow
              key={r.id}
              comment={r}
              contentType={contentType}
              contentId={contentId}
              episodeId={episodeId}
              isReply
            />
          ))}
        </div>
      )}
    </div>
  );
}

/* ── CommentSection ───────────────────────────────────────────────────────── */

export interface CommentSectionProps {
  contentType: number;
  contentId: string;
  episodeId?: number;
  totalComments: number;
  canComment: boolean;
  /** "inline" = rendered in page flow; "sheet" = bottom drawer */
  mode?: "inline" | "sheet";
  isOpen?: boolean;
  onClose?: () => void;
}

function CommentSectionInner({
  contentType,
  contentId,
  episodeId = 0,
  totalComments,
  canComment,
  onClose,
  isInline = false,
}: CommentSectionProps & { isInline?: boolean }) {
  const dispatch = useAppDispatch();
  const key = makeKey(contentType, contentId);
  const entry = useAppSelector((s) => s.comments.entries[key]);
  const { t } = useTranslation();

  const [text, setText] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);
  const requireAuth = useRequireAuth();

  /* Fetch on mount */
  useEffect(() => {
    dispatch(fetchComments({ contentType, contentId, episodeId, pageNo: 1 }));
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [contentType, contentId]);

  const handleLoadMore = useCallback(() => {
    dispatch(fetchComments({ contentType, contentId, episodeId, pageNo: (entry?.currentPage ?? 1) + 1 }));
  }, [dispatch, contentType, contentId, episodeId, entry?.currentPage]);

  const sentinelRef = useInfiniteScroll({
    hasMore: entry?.hasMore ?? false,
    isLoading: (entry?.isLoading || entry?.isLoadingMore) ?? false,
    onLoadMore: handleLoadMore,
  });

  const handleSubmit = useCallback(async () => {
    if (!text.trim() || submitting) return;
    setSubmitting(true);
    const optimisticId = `opt-${Date.now()}`;
    dispatch(
      addOptimistic({
        key,
        comment: {
          id: optimisticId,
          parentId: "0",
          userId: "me",
          channelName: "You",
          avatar: "",
          comment: text.trim(),
          createdAt: "just now",
          isReply: false,
          totalReply: 0,
          isOptimistic: true,
        },
      }),
    );
    await dispatch(
      submitComment({ contentType, contentId, comment: text.trim(), episodeId, optimisticId }),
    );
    setText("");
    setSubmitting(false);
  }, [text, submitting, dispatch, key, contentType, contentId, episodeId]);

  /* Only show top-level comments (parentId = "0") */
  const topLevelComments = (entry?.comments ?? []).filter((c) => c.parentId === "0");
  const displayTotal = entry?.totalRows ?? totalComments;

  return (
    <div className={isInline ? "flex flex-col" : "flex flex-col h-full"}>
      {/* Header */}
      <div
        className="flex items-center justify-between px-4 py-3 shrink-0"
        style={{ borderBottom: "1px solid var(--border)" }}
      >
        <div className="flex items-center gap-2">
          <MessageCircle size={15} style={{ color: "var(--accent)" }} strokeWidth={2} />
          <span className="text-sm font-bold" style={{ color: "var(--text-primary)" }}>{t("feeds_comments")}</span>
          {displayTotal > 0 && (
            <span
              className="text-[9px] font-bold px-2 py-0.5 rounded-full"
              style={{ background: "rgba(var(--accent-rgb),0.12)", color: "var(--accent)", border: "1px solid rgba(var(--accent-rgb),0.2)" }}
            >
              {displayTotal}
            </span>
          )}
        </div>
        {onClose && (
          <button
            className="w-7 h-7 rounded-full flex items-center justify-center transition-all hover:brightness-125"
            style={{ background: "var(--btn-ghost-hover)" }}
            onClick={onClose}
          >
            <X size={13} strokeWidth={2} style={{ color: "var(--text-muted)" }} />
          </button>
        )}
      </div>

      {/* Comment input */}
      {canComment && (
        <div
          className="flex items-center gap-2.5 px-4 py-3 shrink-0"
          style={{ borderBottom: "1px solid var(--border)" }}
        >
          <Avatar src="" name="You" size={32} />
          <div
            className="flex-1 flex items-center gap-2 px-3 py-2 rounded-full transition-all"
            style={{
              background: "var(--btn-ghost)",
              border: "1px solid var(--border)",
            }}
            onClick={() => requireAuth(() => inputRef.current?.focus())}
          >
            <input
              ref={inputRef}
              className="flex-1 bg-transparent outline-none text-[12px]"
              style={{ color: "var(--text-primary)" }}
              placeholder={t("comment_addPlaceholder")}
              value={text}
              onChange={(e) => setText(e.target.value)}
              onKeyDown={(e: KeyboardEvent<HTMLInputElement>) => {
                if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); requireAuth(handleSubmit); }
              }}
            />
            <button
              onClick={() => requireAuth(handleSubmit)}
              disabled={!text.trim() || submitting}
              className="transition-all active:scale-90 disabled:opacity-40"
            >
              <Send
                size={14}
                style={{ color: text.trim() ? "var(--accent)" : "#555" }}
                strokeWidth={2}
              />
            </button>
          </div>
        </div>
      )}

      {/* Comment list — inline: page scrolls; sheet: internal scroll */}
      <div className={isInline ? "px-4 pb-4" : "flex-1 overflow-y-auto scrollbar-thin px-4 pb-4"}>
        {entry?.isLoading ? (
          <div className="flex flex-col gap-3 pt-4">
            {Array.from({ length: 4 }).map((_, i) => (
              <div key={i} className="flex items-start gap-2.5 animate-pulse">
                <div className="w-8 h-8 rounded-full shrink-0" style={{ background: "var(--deep)" }} />
                <div className="flex-1 flex flex-col gap-1.5">
                  <div className="h-2.5 rounded-full" style={{ background: "var(--deep)", width: "35%" }} />
                  <div className="h-2.5 rounded-full" style={{ background: "var(--deep)", width: "85%" }} />
                  <div className="h-2.5 rounded-full" style={{ background: "var(--deep)", width: "60%" }} />
                </div>
              </div>
            ))}
          </div>
        ) : entry?.error ? (
          <div className="flex flex-col items-center justify-center py-12 gap-3">
            <p className="text-xs text-center" style={{ color: "var(--text-muted)" }}>{entry.error}</p>
            <button
              onClick={() => dispatch(fetchComments({ contentType, contentId, episodeId, pageNo: 1 }))}
              className="text-xs font-semibold px-3 py-1.5 rounded-full active:scale-95"
              style={{ background: "var(--accent)", color: "white" }}
            >
              {t("common_retry")}
            </button>
          </div>
        ) : topLevelComments.length === 0 && !entry?.isLoading ? (
          <div className="flex flex-col items-center justify-center py-12 gap-3 text-center">
            <MessageCircle size={28} strokeWidth={1.2} style={{ color: "var(--text-muted)" }} />
            <p className="text-xs" style={{ color: "var(--text-muted)" }}>{t("comment_noComments")}</p>
            {canComment && (
              <p className="text-[11px]" style={{ color: "var(--text-muted)" }}>{t("comment_beFirst")}</p>
            )}
          </div>
        ) : (
          <>
            {topLevelComments.map((c, i) => (
              <div key={c.id}>
                <CommentRow
                  comment={c}
                  contentType={contentType}
                  contentId={contentId}
                  episodeId={episodeId}
                />
                {i < topLevelComments.length - 1 && (
                  <div style={{ height: 1, background: "var(--border-soft)" }} />
                )}
              </div>
            ))}
            <div ref={sentinelRef} className="h-1" />
            {entry?.isLoadingMore && (
              <div className="flex justify-center py-4">
                <div className="flex gap-1.5">
                  {[0, 1, 2].map((i) => (
                    <div
                      key={i}
                      className="w-1.5 h-1.5 rounded-full animate-pulse"
                      style={{ background: "var(--accent)", animationDelay: `${i * 150}ms` }}
                    />
                  ))}
                </div>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}

/* ── Modal dialog wrapper ─────────────────────────────────────────────────── */

function CommentSheet(props: CommentSectionProps) {
  const { isOpen, onClose } = props;

  useEffect(() => {
    if (isOpen) document.body.style.overflow = "hidden";
    else document.body.style.overflow = "";
    return () => { document.body.style.overflow = ""; };
  }, [isOpen]);

  if (!isOpen && !props.contentId) return null;

  return createPortal(
    <>
      {/* Backdrop */}
      <div
        className="fixed inset-0 z-[200]"
        style={{
          background: "rgba(0,0,0,0.75)",
          backdropFilter: isOpen ? "blur(10px)" : "blur(0px)",
          WebkitBackdropFilter: isOpen ? "blur(10px)" : "blur(0px)",
          opacity: isOpen ? 1 : 0,
          pointerEvents: isOpen ? "auto" : "none",
          transition: "opacity 0.22s ease, backdrop-filter 0.22s ease",
        }}
        onClick={onClose}
      />

      {/* Bottom sheet */}
      <div
        className="fixed z-[201] bottom-0 left-0 right-0 flex flex-col overflow-hidden"
        style={{
          maxWidth: "680px",
          margin: "0 auto",
          maxHeight: "82vh",
          background: "var(--sheet-bg)",
          borderRadius: "22px 22px 0 0",
          border: "1px solid var(--sheet-border)",
          borderBottom: "none",
          boxShadow: "0 -24px 64px rgba(0,0,0,0.4)",
          transform: isOpen ? "translateY(0)" : "translateY(100%)",
          opacity: isOpen ? 1 : 0,
          pointerEvents: isOpen ? "auto" : "none",
          transition: isOpen
            ? "transform 0.38s cubic-bezier(0.32, 1.2, 0.56, 1), opacity 0.22s ease"
            : "transform 0.25s ease-in, opacity 0.18s ease-in",
          willChange: "transform, opacity",
        }}
      >
        {/* Drag handle */}
        <div className="flex justify-center pt-3 pb-0 shrink-0">
          <div className="w-9 h-[3px] rounded-full" style={{ background: "var(--sheet-handle)" }} />
        </div>
        <CommentSectionInner {...props} onClose={onClose} />
      </div>
    </>,
    document.body
  );
}

/* ── Public export ────────────────────────────────────────────────────────── */

export function CommentSection(props: CommentSectionProps) {
  if (props.mode === "sheet") {
    return <CommentSheet {...props} />;
  }
  return (
    <div
      className="rounded-2xl w-full"
      style={{
        background: "var(--card)",
        border: "1px solid var(--border)",
      }}
    >
      <CommentSectionInner {...props} isInline />
    </div>
  );
}
