"use client";

import { useActionState, useEffect, useRef, useState, useTransition } from "react";
import Link from "next/link";
import { createComment, deleteComment } from "@/lib/confessions/comment-actions";
import type { listCommentsForConfession } from "@/lib/confessions/comment-queries";
import type { ActionState } from "@/lib/auth/actions";

type Comment = Awaited<ReturnType<typeof listCommentsForConfession>>[number];

function buildThreads(comments: Comment[]) {
  const childrenOf = new Map<string, Comment[]>();
  for (const c of comments) {
    if (!c.parentId) continue;
    const list = childrenOf.get(c.parentId);
    if (list) list.push(c);
    else childrenOf.set(c.parentId, [c]);
  }

  function collectDescendants(id: string): Comment[] {
    const direct = childrenOf.get(id) ?? [];
    return direct.flatMap((child) => [child, ...collectDescendants(child.id)]);
  }

  return comments
    .filter((c) => !c.parentId)
    .map((root) => ({
      root,
      replies: collectDescendants(root.id).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()),
    }));
}

function excerpt(text: string, max = 80) {
  return text.length > max ? `${text.slice(0, max)}...` : text;
}

function CommentForm({
  confessionId,
  parentId,
  onDone,
  autoFocus,
}: {
  confessionId: string;
  parentId: string | null;
  onDone?: () => void;
  autoFocus?: boolean;
}) {
  const action = createComment.bind(null, confessionId);
  const [state, formAction, pending] = useActionState<ActionState, FormData>(action, undefined);
  const formRef = useRef<HTMLFormElement>(null);
  const succeeded = state?.message === "Yorumun eklendi.";

  // Bir üst bileşenin state'ini (yanıt kutusunu kapatma) render sırasında değil, effect içinde
  // güncelliyoruz — "farklı bir bileşeni render sırasında güncelleme" React kısıtını ihlal etmemek için.
  useEffect(() => {
    if (succeeded) onDone?.();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [succeeded]);

  return (
    <form
      ref={formRef}
      action={async (formData) => {
        await formAction(formData);
        formRef.current?.reset();
      }}
      className="flex flex-col gap-2"
    >
      <input type="hidden" name="parentId" value={parentId ?? ""} />
      <textarea
        name="body"
        rows={2}
        maxLength={1000}
        autoFocus={autoFocus}
        placeholder={parentId ? "Yanıtını yaz..." : "Bir yorum yaz..."}
        required
        className="w-full resize-none rounded-xl border border-border px-3.5 py-2.5 text-[13.5px] outline-none focus:border-accent"
      />
      <div className="flex items-center justify-between">
        {state?.message && !succeeded && <p className="text-[12px] text-accent">{state.message}</p>}
        <div className="ml-auto flex gap-2">
          {parentId && (
            <button
              type="button"
              onClick={onDone}
              className="rounded-lg px-3 py-1.5 text-[12.5px] font-semibold text-text-muted hover:bg-bg-alt"
            >
              Vazgeç
            </button>
          )}
          <button
            type="submit"
            disabled={pending}
            className="rounded-lg bg-accent px-4 py-1.5 text-[12.5px] font-semibold text-white hover:bg-accent-dark disabled:opacity-60"
          >
            {pending ? "Gönderiliyor..." : "Gönder"}
          </button>
        </div>
      </div>
    </form>
  );
}

function CommentRow({
  comment,
  confessionId,
  quotedParent,
  viewerId,
  isAdmin,
  replyingTo,
  setReplyingTo,
}: {
  comment: Comment;
  confessionId: string;
  quotedParent: Comment | null;
  viewerId: string | null;
  isAdmin: boolean;
  replyingTo: string | null;
  setReplyingTo: (id: string | null) => void;
}) {
  const fullName = comment.user.profile?.fullName ?? "Bir üye";
  const username = comment.user.profile?.username;
  const initials = fullName.slice(0, 2).toUpperCase();
  const avatarPhoto = comment.user.profile?.avatarPhoto;
  const canDelete = viewerId === comment.userId || isAdmin;
  const isReplying = replyingTo === comment.id;
  const [isDeleting, startDelete] = useTransition();

  return (
    <div className="flex gap-2.5">
      {avatarPhoto ? (
        <div className="h-8 w-8 shrink-0 overflow-hidden rounded-full">
          {/* eslint-disable-next-line @next/next/no-img-element -- yerel diskten servis edilen kullanıcı içeriği */}
          <img src={avatarPhoto.thumbUrl} alt={avatarPhoto.altText ?? fullName} className="h-full w-full object-cover" />
        </div>
      ) : (
        <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-accent to-accent-2 text-[10.5px] font-bold text-white">
          {initials}
        </div>
      )}
      <div className="min-w-0 flex-1">
        <div className="rounded-xl bg-bg-alt px-3.5 py-2.5">
          <div className="flex items-center gap-1.5">
            {username ? (
              <Link href={`/profil/${username}`} className="text-[13px] font-semibold hover:text-accent">
                {fullName}
              </Link>
            ) : (
              <span className="text-[13px] font-semibold">{fullName}</span>
            )}
          </div>
          {quotedParent && (
            <div className="mt-1 rounded-lg border-l-2 border-accent/40 bg-surface px-2.5 py-1.5 text-[11.5px] text-text-muted">
              <span className="font-semibold">{quotedParent.user.profile?.fullName ?? "Bir üye"}:</span>{" "}
              {excerpt(quotedParent.body)}
            </div>
          )}
          <p className="mt-1 whitespace-pre-wrap text-[13.5px] leading-relaxed text-text">{comment.body}</p>
        </div>
        <div className="mt-1 flex items-center gap-3 px-1 text-[11.5px] text-text-muted">
          <span>{comment.createdAt.toLocaleDateString("tr-TR")}</span>
          {viewerId && (
            <button
              type="button"
              onClick={() => setReplyingTo(isReplying ? null : comment.id)}
              className="font-semibold hover:text-accent"
            >
              Yanıtla
            </button>
          )}
          {canDelete && (
            <button
              type="button"
              disabled={isDeleting}
              onClick={() => startDelete(() => deleteComment(comment.id))}
              className="font-semibold hover:text-accent disabled:opacity-60"
            >
              {isDeleting ? "Siliniyor..." : "Sil"}
            </button>
          )}
        </div>

        {isReplying && (
          <div className="mt-2">
            <CommentForm confessionId={confessionId} parentId={comment.id} onDone={() => setReplyingTo(null)} autoFocus />
          </div>
        )}
      </div>
    </div>
  );
}

export function CommentSection({
  confessionId,
  comments,
  viewerId,
  isAdmin,
}: {
  confessionId: string;
  comments: Comment[];
  viewerId: string | null;
  isAdmin: boolean;
}) {
  const [replyingTo, setReplyingTo] = useState<string | null>(null);
  const threads = buildThreads(comments);
  const byId = new Map(comments.map((c) => [c.id, c]));

  return (
    <div className="mt-6 border-t border-dashed border-border pt-6">
      <h2 className="mb-4 text-[15px] font-bold">{comments.length > 0 ? `${comments.length} Yorum` : "Yorumlar"}</h2>

      {viewerId ? (
        <div className="mb-6">
          <CommentForm confessionId={confessionId} parentId={null} />
        </div>
      ) : (
        <p className="mb-6 rounded-xl border border-dashed border-border p-4 text-[13px] text-text-muted">
          Yorum yapmak için{" "}
          <Link href="/giris" className="font-semibold text-accent">
            giriş yap
          </Link>
          .
        </p>
      )}

      {threads.length === 0 ? (
        <p className="text-[13px] text-text-muted">Henüz yorum yapılmamış — ilk yorumu sen yaz.</p>
      ) : (
        <div className="flex flex-col gap-5">
          {threads.map(({ root, replies }) => (
            <div key={root.id} className="flex flex-col gap-3">
              <CommentRow
                comment={root}
                confessionId={confessionId}
                quotedParent={null}
                viewerId={viewerId}
                isAdmin={isAdmin}
                replyingTo={replyingTo}
                setReplyingTo={setReplyingTo}
              />
              {replies.length > 0 && (
                <div className="ml-[42px] flex flex-col gap-3 border-l-2 border-border pl-4">
                  {replies.map((reply) => (
                    <CommentRow
                      key={reply.id}
                      comment={reply}
                      confessionId={confessionId}
                      quotedParent={reply.parentId !== root.id ? (byId.get(reply.parentId!) ?? null) : null}
                      viewerId={viewerId}
                      isAdmin={isAdmin}
                      replyingTo={replyingTo}
                      setReplyingTo={setReplyingTo}
                    />
                  ))}
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
