"use client";

import { useState } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import type { GraphNode } from "@/lib/types";
import { HeartIcon } from "@/components/HeartIcon";
import { formatRelativeTime, buildDescriptionCopyText } from "@/lib/utils";
import {
  STATUS_LABELS,
  STATUS_COLORS,
  PRIORITY_LABELS,
  PRIORITY_COLORS,
  TYPE_ICONS,
  PREFIX_LABELS,
  PREFIX_COLORS,
} from "@/lib/types";
import type { BeadsComment } from "@/hooks/useBeadsComments";

function renderCloseReason(reason: string, repoUrl?: string): React.ReactNode {
  const baseUrl = repoUrl || "https://github.com/GainForest/heartbeads";
  
  const parts = reason.split(/\b([0-9a-f]{7,40})\b/);
  if (parts.length === 1) return reason;
  
  return parts.map((part, i) => {
    if (/^[0-9a-f]{7,40}$/.test(part)) {
      return (
        <a
          key={i}
          href={`${baseUrl}/commit/${part}`}
          target="_blank"
          rel="noopener noreferrer"
          className="font-mono text-emerald-600 dark:text-emerald-400 hover:text-emerald-700 dark:hover:text-emerald-300 underline decoration-emerald-300 hover:decoration-emerald-500 cursor-pointer transition-colors"
        >
          {part}
        </a>
      );
    }
    return <span key={i}>{part}</span>;
  });
}

interface NodeDetailProps {
  node: GraphNode | null;
  allNodes: GraphNode[];
  onNodeNavigate: (nodeId: string) => void;
  comments?: BeadsComment[];
  onPostComment?: (text: string) => Promise<void>;
  onDeleteComment?: (comment: BeadsComment) => Promise<void>;
  onLikeComment?: (comment: BeadsComment) => Promise<void>;
  onReplyComment?: (parentComment: BeadsComment, text: string) => Promise<void>;
  isAuthenticated?: boolean;
  currentDid?: string;
  repoUrls?: Record<string, string>;
  onOpenSettings?: () => void;
  onProfileClick?: (handle: string) => void;
  onShowDescription?: () => void;
}

export default function NodeDetail({
  node,
  allNodes,
  onNodeNavigate,
  comments,
  onPostComment,
  onDeleteComment,
  onLikeComment,
  onReplyComment,
  isAuthenticated,
  currentDid,
  repoUrls,
  onOpenSettings,
  onProfileClick,
  onShowDescription,
}: NodeDetailProps) {
  // Reply state — managed here so it's shared across the comment tree
  const [replyingToUri, setReplyingToUri] = useState<string | null>(null);
  const [replyText, setReplyText] = useState("");
  const [isSubmittingReply, setIsSubmittingReply] = useState(false);
  const [descCopied, setDescCopied] = useState(false);

  const handleStartReply = (comment: BeadsComment) => {
    setReplyingToUri(comment.uri);
    setReplyText("");
  };

  const handleCancelReply = () => {
    setReplyingToUri(null);
    setReplyText("");
  };

  const handleSubmitReply = async () => {
    if (!replyText.trim() || !replyingToUri || !onReplyComment) return;
    setIsSubmittingReply(true);
    try {
      // Find the comment we're replying to
      const findComment = (
        items: BeadsComment[]
      ): BeadsComment | undefined => {
        for (const c of items) {
          if (c.uri === replyingToUri) return c;
          const found = findComment(c.replies);
          if (found) return found;
        }
        return undefined;
      };
      const parentComment = comments
        ? findComment(comments)
        : undefined;
      if (parentComment) {
        await onReplyComment(parentComment, replyText.trim());
      }
      setReplyingToUri(null);
      setReplyText("");
    } catch (err) {
      console.error("Failed to post reply:", err);
    } finally {
      setIsSubmittingReply(false);
    }
  };

  if (!node) {
    return (
      <div className="flex flex-col items-center justify-center py-12 text-center">
        <div className="w-12 h-12 rounded-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center mb-4">
          <svg
            className="w-6 h-6 text-zinc-400 dark:text-zinc-500"
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={1.5}
              d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
            />
          </svg>
        </div>
        <p className="text-sm text-zinc-500 dark:text-zinc-400 leading-relaxed">
          Click a node to see details
        </p>
        <p className="text-xs text-zinc-400 dark:text-zinc-500 mt-1">
          Hover to highlight connections
        </p>
      </div>
    );
  }

  const typeIcon = TYPE_ICONS[node.issueType] || "\uD83D\uDCCB";
  const statusColor = STATUS_COLORS[node.status] || STATUS_COLORS.open;
  const statusLabel = STATUS_LABELS[node.status] || node.status;
  const priorityLabel = PRIORITY_LABELS[node.priority] || `P${node.priority}`;
  const priorityColor = PRIORITY_COLORS[node.priority] || "#a1a1aa";
  const prefixLabel = PREFIX_LABELS[node.prefix] || node.prefix;
  const prefixColor = PREFIX_COLORS[node.prefix] || "#a1a1aa";
  const repoUrl = repoUrls?.[node.prefix];

  // Find blocker and dependent nodes
  const blockerNodes = node.blockerIds
    .map((id) => allNodes.find((n) => n.id === id))
    .filter(Boolean) as GraphNode[];
  const dependentNodes = node.dependentIds
    .map((id) => allNodes.find((n) => n.id === id))
    .filter(Boolean) as GraphNode[];

  // Format date with time
  const formatDate = (dateStr: string) => {
    try {
      const d = new Date(dateStr);
      const date = d.toLocaleDateString("en-US", {
        month: "short",
        day: "numeric",
        year: "numeric",
      });
      const time = d.toLocaleTimeString("en-US", {
        hour: "numeric",
        minute: "2-digit",
        hour12: false,
      });
      return `${date} at ${time}`;
    } catch {
      return dateStr;
    }
  };

  return (
    <div className="animate-fade-in">
      {/* Header */}
      <div className="flex items-start gap-3 mb-4">
        <span className="text-2xl mt-0.5">{typeIcon}</span>
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2">
            <span className="text-xs font-mono font-semibold text-emerald-600 dark:text-emerald-400">
              {node.id}
            </span>
          </div>
          <h3 className="text-sm font-semibold text-zinc-900 dark:text-zinc-100 mt-1 leading-snug">
            {node.title}
          </h3>
        </div>
      </div>

      {/* Badges */}
      <div className="flex flex-wrap gap-2 mb-4">
        {/* Status badge */}
        <span
          className="status-badge"
          style={{
            backgroundColor: statusColor + "18",
            color: statusColor,
            border: `1px solid ${statusColor}30`,
          }}
        >
          <span
            className="w-1.5 h-1.5 rounded-full mr-1.5"
            style={{ backgroundColor: statusColor }}
          />
          {statusLabel}
        </span>

        {/* Priority */}
        <span
          className="status-badge"
          style={{
            backgroundColor: priorityColor + "15",
            color: priorityColor,
            border: `1px solid ${priorityColor}25`,
          }}
        >
          {priorityLabel}
        </span>

        {/* Project prefix */}
        {repoUrl ? (
          <a
            href={repoUrl}
            target="_blank"
            rel="noopener noreferrer"
            className="status-badge hover:opacity-80 transition-opacity"
            style={{
              backgroundColor: prefixColor + "15",
              color: prefixColor,
              border: `1px solid ${prefixColor}25`,
              textDecoration: "none",
            }}
          >
            {prefixLabel}
            <svg className="w-2.5 h-2.5 ml-1 opacity-50" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
              <path strokeLinecap="round" strokeLinejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
            </svg>
          </a>
        ) : (
          <span
            className="status-badge"
            style={{
              backgroundColor: prefixColor + "15",
              color: prefixColor,
              border: `1px solid ${prefixColor}25`,
            }}
          >
            {prefixLabel}
          </span>
        )}
      </div>

      {/* Labels */}
      {node.labels.length > 0 && (
        <div className="flex flex-wrap gap-1.5 mb-4">
          {node.labels.map((label) => (
            <span
              key={label}
              className="inline-flex items-center px-2 py-0.5 rounded-full text-[11px] font-medium bg-zinc-100 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 border border-zinc-200/60 dark:border-zinc-700/60"
            >
              {label}
            </span>
          ))}
        </div>
      )}

      {/* Repository link */}
      {repoUrl && (
        <div className="mb-4">
          <a
            href={repoUrl}
            target="_blank"
            rel="noopener noreferrer"
            className="inline-flex items-center gap-1.5 text-[11px] text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-300 transition-colors"
          >
            <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="currentColor">
              <path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z" />
            </svg>
            {repoUrl.replace(/^https?:\/\//, "")}
          </a>
        </div>
      )}

      {/* Metrics grid */}
      <div className="grid grid-cols-2 gap-3 mb-4">
        <MetricCard
          label="Blocks"
          value={node.blockerCount}
          color={node.blockerCount > 0 ? "#f59e0b" : undefined}
        />
        <MetricCard
          label="Blocked by"
          value={node.dependentCount}
          color={node.dependentCount > 0 ? "#ef4444" : undefined}
        />
      </div>

      {/* Dates */}
      <div className="space-y-1.5 mb-4 text-xs text-zinc-500 dark:text-zinc-400">
        <div className="flex justify-between">
          <span>Created</span>
          <span className="text-zinc-700 dark:text-zinc-300 font-medium">
            {formatDate(node.createdAt)}
          </span>
        </div>
        <div className="flex justify-between">
          <span>Updated</span>
          <span className="text-zinc-700 dark:text-zinc-300 font-medium">
            {formatDate(node.updatedAt)}
          </span>
        </div>
        {node.closedAt && (
          <div className="flex justify-between">
            <span>Closed</span>
            <span className="text-zinc-700 dark:text-zinc-300 font-medium">
              {formatDate(node.closedAt)}
            </span>
          </div>
        )}
        {node.closeReason && (
          <div className="flex justify-between">
            <span>Reason</span>
            <span className="text-zinc-700 dark:text-zinc-300 font-medium ml-2 text-right">
              {renderCloseReason(node.closeReason, repoUrl)}
            </span>
          </div>
        )}
        {node.createdBy && (
          <div className="flex justify-between">
            <span>Created by</span>
            <button
              onClick={() => onProfileClick?.(node.createdBy!)}
              className="text-zinc-700 dark:text-zinc-300 font-medium truncate ml-2 hover:text-emerald-600 dark:hover:text-emerald-400 transition-colors"
            >
              {node.createdBy}
            </button>
          </div>
        )}
        {node.owner && node.owner !== node.createdBy && (
          <div className="flex justify-between">
            <span>Owner</span>
            <button
              onClick={() => onProfileClick?.(node.owner!)}
              className="text-zinc-700 dark:text-zinc-300 font-medium truncate ml-2 hover:text-emerald-600 dark:hover:text-emerald-400 transition-colors"
            >
              {node.owner}
            </button>
          </div>
        )}
        <div className="flex justify-between">
          <span>Assignee</span>
          {node.assignee ? (
            <button
              onClick={() => onProfileClick?.(node.assignee!)}
              className="text-zinc-700 dark:text-zinc-300 font-medium truncate ml-2 hover:text-emerald-600 dark:hover:text-emerald-400 transition-colors"
            >
              {node.assignee}
            </button>
          ) : (
            <span className="text-zinc-400 dark:text-zinc-500 italic ml-2">
              No assignee
            </span>
          )}
        </div>
        {node.estimatedMinutes != null && (
          <div className="flex justify-between">
            <span>Estimate</span>
            <span className="text-zinc-700 dark:text-zinc-300 font-medium">
              ⏱ {node.estimatedMinutes}m
            </span>
          </div>
        )}
      </div>

      {/* Description */}
      {node.description && (
        <div className="mb-4">
          <div className="flex items-center justify-between mb-2">
            <h4 className="text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
              Description
            </h4>
            <div className="flex items-center gap-2">
              <button
                onClick={() => {
                  if (!node.description) return;
                  const repoUrl = repoUrls?.[node.prefix];
                  navigator.clipboard.writeText(buildDescriptionCopyText(node, repoUrl)).then(() => {
                    setDescCopied(true);
                    setTimeout(() => setDescCopied(false), 1500);
                  });
                }}
                className="text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-300 transition-colors"
                title="Copy description"
              >
                {descCopied ? (
                  <svg className="w-3.5 h-3.5 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
                  </svg>
                ) : (
                  <svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M15.666 3.888A2.25 2.25 0 0 0 13.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 0 1-.75.75H9.75a.75.75 0 0 1-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 0 1-2.25 2.25H6.75A2.25 2.25 0 0 1 4.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 0 1 1.927-.184" />
                  </svg>
                )}
              </button>
              <button
                onClick={() => onShowDescription?.()}
                className="text-[10px] text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-300 transition-colors"
              >
                View in window
              </button>
            </div>
          </div>
          <div className="text-xs text-zinc-600 dark:text-zinc-300 leading-relaxed bg-zinc-50 dark:bg-zinc-800 rounded-lg p-3 max-h-40 overflow-y-auto custom-scrollbar border border-zinc-100 dark:border-zinc-800 description-markdown">
            <ReactMarkdown remarkPlugins={[remarkGfm]}>
              {node.description}
            </ReactMarkdown>
          </div>
        </div>
      )}

      {/* Acceptance Criteria */}
      {node.acceptanceCriteria && (
        <div className="mb-4">
          <h4 className="text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2">
            Acceptance Criteria
          </h4>
          <pre className="text-[11px] font-mono bg-zinc-50 dark:bg-zinc-800 rounded-lg p-3 border border-zinc-100 dark:border-zinc-800 overflow-x-auto whitespace-pre-wrap break-all">
            <code>{node.acceptanceCriteria}</code>
          </pre>
        </div>
      )}

      {/* Blocks (issues this blocks) */}
      {blockerNodes.length > 0 && (
        <div className="mb-4">
          <h4 className="text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2">
            Blocks ({blockerNodes.length})
          </h4>
          <div className="space-y-1">
            {blockerNodes.map((dep) => (
              <DependencyLink
                key={dep.id}
                node={dep}
                onClick={() => onNodeNavigate(dep.id)}
              />
            ))}
          </div>
        </div>
      )}

      {/* Blocked by */}
      {dependentNodes.length > 0 && (
        <div className="mb-4">
          <h4 className="text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2">
            Blocked by ({dependentNodes.length})
          </h4>
          <div className="space-y-1">
            {dependentNodes.map((dep) => (
              <DependencyLink
                key={dep.id}
                node={dep}
                onClick={() => onNodeNavigate(dep.id)}
              />
            ))}
          </div>
        </div>
      )}

      {/* Comments */}
      <div className="mb-4">
        <h4 className="text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2">
          Comments{" "}
          {comments && comments.length > 0 && (
            <span className="ml-1 px-1.5 py-0.5 bg-emerald-50 dark:bg-emerald-950 text-emerald-600 dark:text-emerald-400 rounded-full text-[10px] font-medium">
              {comments.length}
            </span>
          )}
        </h4>

        {/* Comment list */}
        {comments && comments.length > 0 ? (
          <div className="space-y-1">
            {comments.map((comment) => (
              <CommentItem
                key={comment.uri}
                comment={comment}
                currentDid={currentDid}
                isAuthenticated={isAuthenticated}
                onDelete={onDeleteComment}
                onLike={onLikeComment}
                onStartReply={handleStartReply}
                replyingToUri={replyingToUri}
                replyText={replyText}
                onReplyTextChange={setReplyText}
                onSubmitReply={handleSubmitReply}
                onCancelReply={handleCancelReply}
                isSubmittingReply={isSubmittingReply}
                depth={0}
              />
            ))}
          </div>
        ) : (
          <p className="text-xs text-zinc-400 dark:text-zinc-500 italic">No comments yet</p>
        )}

        {/* Compose area */}
        {isAuthenticated && onPostComment ? (
          <CommentCompose onSubmit={onPostComment} />
        ) : !isAuthenticated ? (
          <p className="text-xs text-zinc-400 dark:text-zinc-500 mt-2">
            Sign in to leave a comment
          </p>
        ) : null}
      </div>
    </div>
  );
}



// ============================================================================
// InlineReplyForm — ported from Hyperscan ReviewSection
// ============================================================================

function InlineReplyForm({
  replyingTo,
  replyText,
  onTextChange,
  onSubmit,
  onCancel,
  isSubmitting,
}: {
  replyingTo: BeadsComment;
  replyText: string;
  onTextChange: (text: string) => void;
  onSubmit: () => void;
  onCancel: () => void;
  isSubmitting: boolean;
}) {
  return (
    <div className="mt-2 ml-4 pl-3 border-l border-emerald-200 space-y-1.5">
      <div className="flex items-center gap-1.5 text-[10px] text-zinc-400 dark:text-zinc-500">
        <span>Replying to</span>
        <a
          href={`https://www.impactindexer.org/data?did=${replyingTo.did}`}
          target="_blank"
          rel="noopener noreferrer"
          className="font-medium text-zinc-600 dark:text-zinc-400 hover:text-emerald-600 dark:hover:text-emerald-400 transition-colors"
        >
          {replyingTo.displayName || replyingTo.handle}
        </a>
      </div>
      <div className="flex gap-2">
        <input
          type="text"
          value={replyText}
          onChange={(e) => onTextChange(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) onSubmit();
          }}
          placeholder="Write a reply..."
          disabled={isSubmitting}
          autoFocus
          className="flex-1 px-2 py-1 text-xs bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded placeholder-zinc-400 dark:placeholder-zinc-500 focus:outline-none focus:border-emerald-400 disabled:opacity-50"
        />
        <button
          onClick={onSubmit}
          disabled={!replyText.trim() || isSubmitting}
          className="px-2 py-1 text-[10px] font-medium text-emerald-600 dark:text-emerald-400 hover:text-emerald-700 dark:hover:text-emerald-300 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
        >
          {isSubmitting ? "..." : "Reply"}
        </button>
        <button
          onClick={onCancel}
          disabled={isSubmitting}
          className="px-2 py-1 text-[10px] text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-300 disabled:opacity-50 transition-colors"
        >
          Cancel
        </button>
      </div>
    </div>
  );
}

// ============================================================================
// Sub-components
// ============================================================================

function MetricCard({
  label,
  value,
  color,
}: {
  label: string;
  value: number;
  color?: string;
}) {
  return (
    <div className="bg-zinc-50 dark:bg-zinc-800 rounded-lg p-3 border border-zinc-100 dark:border-zinc-800">
      <div
        className="text-xl font-bold"
        style={{ color: color || "#3f3f46" }}
      >
        {value}
      </div>
      <div className="text-[10px] text-zinc-400 dark:text-zinc-500 uppercase tracking-wider mt-0.5">
        {label}
      </div>
    </div>
  );
}

function DependencyLink({
  node,
  onClick,
}: {
  node: GraphNode;
  onClick: () => void;
}) {
  const statusColor = STATUS_COLORS[node.status] || STATUS_COLORS.open;

  return (
    <button
      onClick={onClick}
      className="w-full flex items-center gap-2 px-2.5 py-1.5 rounded-md hover:bg-zinc-50 dark:hover:bg-zinc-800 transition-colors text-left group border border-transparent hover:border-zinc-200 dark:hover:border-zinc-700"
    >
      <span
        className="w-2 h-2 rounded-full shrink-0"
        style={{ backgroundColor: statusColor }}
      />
      <span className="text-xs font-mono text-emerald-600 dark:text-emerald-400 group-hover:text-emerald-700 dark:group-hover:text-emerald-300 shrink-0">
        {node.id}
      </span>
      <span className="text-xs text-zinc-500 dark:text-zinc-400 truncate">{node.title}</span>
    </button>
  );
}

function CommentItem({
  comment,
  currentDid,
  isAuthenticated,
  onDelete,
  onLike,
  onStartReply,
  replyingToUri,
  replyText,
  onReplyTextChange,
  onSubmitReply,
  onCancelReply,
  isSubmittingReply,
  depth,
}: {
  comment: BeadsComment;
  currentDid?: string;
  isAuthenticated?: boolean;
  onDelete?: (comment: BeadsComment) => Promise<void>;
  onLike?: (comment: BeadsComment) => Promise<void>;
  onStartReply: (comment: BeadsComment) => void;
  replyingToUri: string | null;
  replyText: string;
  onReplyTextChange: (text: string) => void;
  onSubmitReply: () => void;
  onCancelReply: () => void;
  isSubmittingReply: boolean;
  depth: number;
}) {
  const [deleting, setDeleting] = useState(false);
  const [liking, setLiking] = useState(false);
  const isOwn = currentDid && currentDid === comment.did;
  const hasLiked = currentDid
    ? comment.likes.some((l) => l.did === currentDid)
    : false;
  const isReplyingToThis = replyingToUri === comment.uri;

  const handleDelete = async () => {
    if (!onDelete || deleting) return;
    setDeleting(true);
    try {
      await onDelete(comment);
    } catch (err) {
      console.error("Failed to delete comment:", err);
    } finally {
      setDeleting(false);
    }
  };

  const handleLike = async () => {
    if (!onLike || liking) return;
    setLiking(true);
    try {
      await onLike(comment);
    } catch (err) {
      console.error("Failed to toggle like:", err);
    } finally {
      setLiking(false);
    }
  };

  return (
    <div className={`${depth > 0 ? "ml-4 pl-3 border-l border-zinc-100 dark:border-zinc-800" : ""}`}>
      <div className="py-2">
        {/* Header: avatar + name + date */}
        <div className="flex items-center gap-1.5 mb-1">
          <div className="shrink-0 w-4 h-4 rounded-full bg-zinc-100 dark:bg-zinc-800 overflow-hidden">
            {comment.avatar ? (
              <img
                src={comment.avatar}
                alt=""
                className="w-full h-full object-cover"
              />
            ) : (
              <div className="w-full h-full flex items-center justify-center text-[8px] font-medium text-zinc-400 dark:text-zinc-500">
                {(comment.handle || comment.did).charAt(0).toUpperCase()}
              </div>
            )}
          </div>
          <a
            href={`https://www.impactindexer.org/data?did=${comment.did}`}
            target="_blank"
            rel="noopener noreferrer"
            className="text-xs font-medium text-zinc-600 dark:text-zinc-400 truncate hover:text-emerald-600 dark:hover:text-emerald-400 transition-colors"
          >
            {comment.displayName ||
              comment.handle ||
              comment.did.slice(0, 16) + "..."}
          </a>
          <span className="text-[10px] text-zinc-300 dark:text-zinc-600 shrink-0">
            {formatRelativeTime(comment.createdAt)}
          </span>
        </div>

        {/* Comment text */}
        <p className="text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed whitespace-pre-wrap break-words">
          {comment.text}
        </p>

        {/* Actions row: like, reply, delete */}
        <div className="flex items-center gap-2 mt-1 text-[10px]">
          {/* Like button */}
          <button
            onClick={handleLike}
            disabled={!isAuthenticated || liking}
            className={`flex items-center gap-0.5 transition-colors ${
              hasLiked
                ? "text-rose-500"
                : "text-zinc-300 hover:text-rose-500"
            } disabled:opacity-50`}
          >
            <HeartIcon className="w-3 h-3" filled={hasLiked} />
            {comment.likes.length > 0 && (
              <span>{comment.likes.length}</span>
            )}
          </button>

          {/* Reply button */}
          <button
            onClick={() => onStartReply(comment)}
            disabled={!isAuthenticated}
            className={`transition-colors disabled:opacity-50 ${
              isReplyingToThis
                ? "text-emerald-500 dark:text-emerald-400"
                : "text-zinc-300 dark:text-zinc-600 hover:text-zinc-500 dark:hover:text-zinc-400"
            }`}
          >
            reply
          </button>

          {/* Delete button — only for own comments */}
          {isOwn && onDelete && (
            <button
              onClick={handleDelete}
              disabled={deleting}
              className="ml-auto shrink-0 text-zinc-300 dark:text-zinc-600 hover:text-red-400 disabled:opacity-50 transition-colors"
            >
              {deleting ? "..." : "delete"}
            </button>
          )}
        </div>
      </div>

      {/* Inline reply form */}
      {isReplyingToThis && (
        <InlineReplyForm
          replyingTo={comment}
          replyText={replyText}
          onTextChange={onReplyTextChange}
          onSubmit={onSubmitReply}
          onCancel={onCancelReply}
          isSubmitting={isSubmittingReply}
        />
      )}

      {/* Nested replies */}
      {comment.replies.length > 0 && (
        <div>
          {comment.replies.map((reply) => (
            <CommentItem
              key={reply.uri}
              comment={reply}
              currentDid={currentDid}
              isAuthenticated={isAuthenticated}
              onDelete={onDelete}
              onLike={onLike}
              onStartReply={onStartReply}
              replyingToUri={replyingToUri}
              replyText={replyText}
              onReplyTextChange={onReplyTextChange}
              onSubmitReply={onSubmitReply}
              onCancelReply={onCancelReply}
              isSubmittingReply={isSubmittingReply}
              depth={depth + 1}
            />
          ))}
        </div>
      )}
    </div>
  );
}

function CommentCompose({
  onSubmit,
}: {
  onSubmit: (text: string) => Promise<void>;
}) {
  const [text, setText] = useState("");
  const [sending, setSending] = useState(false);

  const handleSubmit = async () => {
    if (!text.trim() || sending) return;
    setSending(true);
    try {
      await onSubmit(text.trim());
      setText("");
    } catch (err) {
      console.error("Failed to post comment:", err);
    } finally {
      setSending(false);
    }
  };

  return (
    <div className="mt-3 space-y-2">
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Leave a comment..."
        rows={2}
        className="w-full px-2.5 py-1.5 text-xs border border-zinc-200 dark:border-zinc-700 rounded-md bg-zinc-50 dark:bg-zinc-800 text-zinc-700 dark:text-zinc-300 placeholder-zinc-400 dark:placeholder-zinc-500 resize-none focus:outline-none focus:ring-1 focus:ring-emerald-500 focus:border-emerald-500"
      />
      <button
        onClick={handleSubmit}
        disabled={!text.trim() || sending}
        className="px-3 py-1 text-xs font-medium text-white bg-emerald-500 rounded-md hover:bg-emerald-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
      >
        {sending ? "Sending..." : "Comment"}
      </button>
    </div>
  );
}


