import { useEffect, useState } from "react";
import { useBackLayer } from "../../app/useBackLayer.js";
import { ActivityCard } from "./ActivityCard.jsx";
import { ApprovalCard } from "./ApprovalCard.jsx";
import { activityItemsBetween, activityLogCount } from "./activity-card.js";
import { AssistantMarkdown } from "./AssistantMarkdown.jsx";
import { MessageCopyButton } from "./MessageCopyButton.jsx";
import { ImageGallery } from "./ImageGallery.jsx";
import { useI18n } from "../../shared/I18nProvider.jsx";
export function ConversationTurn({ turn, now, approvalDecisionPending, onDecision, onRetry, changedFiles, onOpenChangedFile }) {
  const { t } = useI18n();
  const sections = turnSections(turn);
  const [activeMessageId, setActiveMessageId] = useState(null);
  const [gallery, setGallery] = useState(null);
  useBackLayer(Boolean(activeMessageId), () => setActiveMessageId(null), "message-actions");

  useEffect(() => {
    if (!activeMessageId) return undefined;
    const dismissOutside = (event) => {
      const message = event.target?.closest?.("[data-message-action-id]");
      if (message?.dataset.messageActionId !== activeMessageId) setActiveMessageId(null);
    };
    const dismissOnEscape = (event) => {
      if (event.key === "Escape") setActiveMessageId(null);
    };
    document.addEventListener("pointerdown", dismissOutside);
    document.addEventListener("keydown", dismissOnEscape);
    return () => {
      document.removeEventListener("pointerdown", dismissOutside);
      document.removeEventListener("keydown", dismissOnEscape);
    };
  }, [activeMessageId]);

  function openMessageActions(event, messageId) {
    const selection = globalThis.getSelection?.();
    const selectingMessageText = selection && !selection.isCollapsed && event.currentTarget.contains(selection.anchorNode);
    if (event.target?.closest?.("a, button") || selectingMessageText) return;
    setActiveMessageId((current) => current === messageId ? null : messageId);
  }

  function handleMessageKeyDown(event, messageId) {
    if (event.key === "Escape") {
      setActiveMessageId(null);
      return;
    }
    if (event.key !== "Enter" && event.key !== " ") return;
    event.preventDefault();
    setActiveMessageId((current) => current === messageId ? null : messageId);
  }

  return <article className="conversation-turn">
    {sections.map((section) => <TurnSection section={section} now={now} approvalDecisionPending={approvalDecisionPending} onDecision={onDecision} onRetry={onRetry} changedFiles={changedFiles} onOpenChangedFile={onOpenChangedFile} activeMessageId={activeMessageId} onMessageClick={openMessageActions} onMessageKeyDown={handleMessageKeyDown} onDismissMessageActions={() => setActiveMessageId(null)} onOpenGallery={(images, index) => setGallery({ images, index })} t={t} key={section.id} />)}
    {turn.assistantText && <MessageBubble messageId={`${turn.id}-assistant`} text={turn.assistantText} side="assistant" alwaysShowActions activeMessageId={activeMessageId} onMessageClick={openMessageActions} onMessageKeyDown={handleMessageKeyDown} onDismiss={() => setActiveMessageId(null)}><AssistantMarkdown>{turn.assistantText}</AssistantMarkdown></MessageBubble>}
    {turn.approvals.filter((a) => a.status === "pending").map((a) => <ApprovalCard key={a.id} approval={a} decisionPending={approvalDecisionPending === a.id} onDecision={onDecision} />)}
    {gallery && <ImageGallery images={gallery.images} initialIndex={gallery.index} onClose={() => setGallery(null)} />}
  </article>;
}

function TurnSection({ section, now, approvalDecisionPending, onDecision, onRetry, changedFiles, onOpenChangedFile, activeMessageId, onMessageClick, onMessageKeyDown, onDismissMessageActions, onOpenGallery, t }) {
  return <>
    {(section.message.text || section.message.attachments?.length > 0) && <UserMessage message={section.message} messageId={`${section.id}-user`} activeMessageId={activeMessageId} onMessageClick={onMessageClick} onMessageKeyDown={onMessageKeyDown} onDismiss={onDismissMessageActions} onOpenGallery={onOpenGallery} t={t} />}
    {section.showActivity && <ActivityCard turn={section.turn} now={now} approvalDecisionPending={approvalDecisionPending} onDecision={onDecision} onRetry={onRetry} changedFiles={changedFiles} onOpenChangedFile={onOpenChangedFile} />}
  </>;
}

function UserMessage({ message, messageId, activeMessageId, onMessageClick, onMessageKeyDown, onDismiss, onOpenGallery, t }) {
  const attachments = message.attachments ?? [];
  const availableAttachments = attachments.filter((item) => !item.deleted);
  return <>
    {attachments.length > 0 && <div className="message-attachments user-attachments">{attachments.map((item) => item.deleted
      ? <span className="message-attachment-deleted" key={item.id}>{t("conversation.attachmentDeleted")}</span>
      : <button type="button" className="message-attachment-button" key={item.id} aria-label={t("gallery.open", { name: item.name || t("conversation.image") })} onClick={() => onOpenGallery(availableAttachments, availableAttachments.indexOf(item))}><img className="message-attachment-preview" src={item.previewUrl} alt={item.name || t("conversation.attachedImage")} /></button>)}</div>}
    {message.text && <MessageBubble messageId={messageId} text={message.text} side="user" activeMessageId={activeMessageId} onMessageClick={onMessageClick} onMessageKeyDown={onMessageKeyDown} onDismiss={onDismiss}><div className="message user">{message.text}</div></MessageBubble>}
    {message.status === "sending" && <span className="message-send-status">{t("conversation.sending")}</span>}
  </>;
}

function MessageBubble({ messageId, text, side, alwaysShowActions = false, activeMessageId, onMessageClick, onMessageKeyDown: handleMessageKeyDown, onDismiss, children }) {
  const open = activeMessageId === messageId;
  const actionsVisible = alwaysShowActions || open;
  return <div className={`message-with-actions ${side}-message`} data-message-action-id={messageId}>
    <div className="message-action-trigger" role="button" tabIndex="0" aria-haspopup="menu" aria-expanded={actionsVisible} onClick={(event) => onMessageClick(event, messageId)} onKeyDown={(event) => handleMessageKeyDown(event, messageId)}>
      {children}
    </div>
    <div className={`message-copy-popover ${actionsVisible ? "is-open" : ""}`} role="menu" aria-hidden={!actionsVisible}><MessageCopyButton text={text} active={actionsVisible} onDismiss={onDismiss} /></div>
  </div>;
}

function turnSections(turn) {
  const userMessages = turn.userMessages ?? (turn.userTexts ?? (turn.userText ? [turn.userText] : []))
    .map((text, index) => ({
      text,
      createdAt: index === 0 ? turn.startedAt : Number.POSITIVE_INFINITY,
      attachments: index === 0 ? turn.userAttachments : []
    }));
  const messages = userMessages.length > 0 ? userMessages : [{ text: turn.userText ?? "", createdAt: turn.startedAt, attachments: turn.userAttachments ?? [] }];
  const totalLogCount = activityLogCount(turn);
  return messages.map((message, index) => {
    const nextMessage = messages[index + 1];
    const isLast = index === messages.length - 1;
    const sectionTurn = {
      ...turn,
      id: `${turn.id}-section-${index}`,
      userText: message.text,
      userTexts: [message.text],
      userAttachments: message.attachments ?? [],
      status: isLast ? turn.status : "completed",
      completedAt: isLast ? turn.completedAt : nextMessage?.createdAt,
      activity: {
        ...turn.activity,
        items: activityItemsBetween(turn.activity.items ?? [], message.createdAt, nextMessage?.createdAt),
        plan: isLast ? turn.activity.plan : [],
        fileCount: isLast ? turn.activity.fileCount : 0,
        durationMs: isLast ? turn.activity.durationMs : durationBetween(turn.startedAt, nextMessage?.createdAt)
      },
      approvals: isLast ? turn.approvals : [],
      error: isLast ? turn.error : undefined
    };
    const sectionMessage = {
      ...message,
      status: isLast && turn.status === "sending" ? "sending" : undefined
    };
    const isActive = isLast && ["thinking", "running", "waiting_approval", "waiting_response"].includes(turn.status);
    const isStopped = isLast && turn.status === "interrupted";
    const sectionLogCount = activityLogCount(sectionTurn);
    return {
      id: sectionTurn.id,
      message: sectionMessage,
      turn: sectionTurn,
      showActivity: sectionLogCount > 0 || ((isActive || isStopped) && totalLogCount === 0)
    };
  });
}

function durationBetween(startedAt, completedAt) {
  if (!Number.isFinite(startedAt) || !Number.isFinite(completedAt)) return undefined;
  return Math.max(0, completedAt - startedAt);
}
