import type { ChatPageContext } from "../../context";
import { t } from "#cli/i18n";
import { textCellWidth, TText, TView } from "@simon_he/vue-tui";
import { h } from "vue";
import { DimSdkMessageActionsDialog } from "../../../../ui/components/MessageActionsDialog";
import { DimSdkRedoConfirmDialog } from "../../../../ui/components/RedoConfirmDialog";

export function renderMessageOverlays(ctx: ChatPageContext) {
  const nodes: any[] = [];

  if (ctx.store.hasRevertedMessages.value) {
    const ui = ctx.ui;
    const bannerH = 2;
    const bannerX = 2;
    const bannerY = ctx.mainY + ctx.mainH.value;
    const bannerW = Math.max(0, ctx.mainW.value - 4);
    const bannerFill = (() => {
      const w = Math.max(0, bannerW);
      const h = Math.max(0, bannerH);
      if (w === 0 || h === 0) return "";
      const line = " ".repeat(w);
      return Array.from({ length: h }, () => line).join("\n");
    })();
    const barText = Array.from({ length: bannerH }, () => "▏").join("\n");
    const textX = bannerX + 2;
    const textW = Math.max(0, bannerW - 3);
    nodes.push(
      h(TText, {
        key: "revert-banner-bg",
        x: bannerX,
        y: bannerY,
        w: bannerW,
        h: bannerH,
        value: bannerFill,
        style: ui.style(["bg.chrome"]),
        zIndex: 50,
      }),
      h(TText, {
        key: "revert-banner-bar",
        x: bannerX,
        y: bannerY,
        w: 1,
        h: bannerH,
        value: barText,
        style: ui.style(["accent.cyan", "bg.chrome"]),
        zIndex: 51,
      }),
      h(TText, {
        key: "revert-banner-text",
        x: textX,
        y: bannerY,
        w: textW,
        value: `${ctx.store.revertedMessageCount.value} message${ctx.store.revertedMessageCount.value > 1 ? "s" : ""} reverted`,
        style: ui.style(["status.warning", "bg.chrome"]),
        zIndex: 52,
      }),
      h(TText, {
        key: "revert-banner-hint",
        x: textX,
        y: bannerY + 1,
        w: textW,
        value: "click or ctrl+r or /redo to restore",
        style: ui.style(["text.muted", "bg.chrome"], { bold: true }),
        zIndex: 52,
      }),
      h(TView, {
        key: "revert-banner-hit",
        x: bannerX,
        y: bannerY,
        w: bannerW,
        h: bannerH,
        zIndex: 60,
        focusable: true,
        onClick: () => {
          ctx.confirmRestore();
          ctx.focusBrowserTextarea();
        },
      }),
    );
  }

  const mainH = Math.max(0, Math.floor(ctx.mainH.value));
  const maxTop = Math.max(0, Math.floor(ctx.maxScroll?.value ?? 0));
  const scrollTop = Math.max(0, Math.min(maxTop, Math.floor(ctx.scrollTop.value)));
  const distanceFromBottom = Math.max(0, maxTop - scrollTop);
  const jumpMinDistance = Math.max(8, mainH);
  const showJumpToBottom =
    !ctx.anyDialogOpen.value && maxTop > 0 && distanceFromBottom >= jumpMinDistance && mainH > 0;

  if (showJumpToBottom) {
    const label = `[ ${t("chatPage.jumpToBottom.button")} ]`;
    const buttonW = textCellWidth(label);
    const messageW = Math.max(0, ctx.mainW.value - 5);
    const buttonX = Math.max(2, 2 + messageW - buttonW);
    const buttonY = Math.max(ctx.mainY, Math.floor(ctx.panelTopY.value) - 2);
    const style = ctx.ui.style(["text.primary", "bg.chrome"], { bold: true });
    const handleJumpToBottom = (e?: any) => {
      e?.preventDefault?.();
      e?.stopPropagation?.();
      ctx.scrollTop.value = maxTop;
      if (ctx.stickToBottom) ctx.stickToBottom.value = true;
      ctx.invalidate();
    };
    nodes.push(
      h(TText, {
        key: "jump-bottom-label",
        x: buttonX,
        y: buttonY,
        w: buttonW,
        h: 1,
        value: label,
        style,
        zIndex: 70,
        clear: true,
      }),
      h(TView, {
        key: "jump-bottom-hit",
        id: "chat-jump-bottom-hit",
        x: buttonX,
        y: buttonY,
        w: buttonW,
        h: 1,
        zIndex: 71,
        focusable: false,
        onClick: handleJumpToBottom,
        onPointerdown: handleJumpToBottom,
      }),
    );
  }

  nodes.push(
    h(DimSdkMessageActionsDialog, {
      w: ctx.mdW.value,
      modelValue: ctx.showMessageActions.value,
      "onUpdate:modelValue": (v: boolean) => {
        ctx.showMessageActions.value = v;
        if (!v) {
          ctx.messageActionsTargetId.value = null;
          ctx.messageActionsIndex.value = 0;
          ctx.messageActionsMode.value = "full";
        }
      },
      mode: ctx.messageActionsMode.value,
      pinLabel:
        ctx.messageActionsTargetId.value && ctx.isMessagePinned(ctx.messageActionsTargetId.value)
          ? t("messageActionsDialog.unpin")
          : t("messageActionsDialog.pin"),
      selectedIndex: ctx.messageActionsIndex.value,
      "onUpdate:selectedIndex": (v: number) => (ctx.messageActionsIndex.value = v),
      onAction: (action: any) => {
        if (action === "revert")
          if (ctx.messageActionsMode.value === "changed_files")
            ctx.handleRevertTurnMessageAndFiles();
          else ctx.handleRevertMessage();
        else if (action === "revert_keep_files") ctx.handleRevertMessageKeepFiles();
        else if (action === "revert_files_only") ctx.handleRevertFilesOnly();
        else if (action === "copy") ctx.handleCopyMessage();
        else if (action === "pin") ctx.handlePinMessage();
        else ctx.handleForkSession();
      },
    }),
    h(DimSdkRedoConfirmDialog, {
      w: ctx.smW.value,
      h: ctx.smH.value,
      modelValue: ctx.showRedoConfirm.value,
      "onUpdate:modelValue": (v: boolean) => (ctx.showRedoConfirm.value = v),
      onConfirm: ctx.confirmRestore,
      onCancel: ctx.cancelRestore,
    }),
  );

  return nodes;
}
