// SPEC: PJ2026-01040409 MDTODO前端重写; draft-2026-06-26-p0-mdtodo-web-rewrite.
// Responsibility: Workbench launch with first-round task context via public Launch API.

import { ref } from "vue";
import { agentAPI, workbenchAPI, type MdtodoTaskLinkRecord, type MdtodoTaskRecord, type ProjectNavigationResponse } from "@/api";
import { apiErrorContextFromUnknown } from "@/api/client";
import type { ApiError, ErrorDiagnostic } from "@/types";
import type { Router } from "vue-router";

export interface WorkbenchLaunchContext {
  source: string;
  projectId: string;
  taskRef: string;
  sourceId?: string;
  sourceKind?: string | null;
  fileRef?: string;
  relativePath?: string | null;
  fileName?: string;
  taskId?: string;
  title?: string;
  status?: string;
  hwpodId?: string | null;
  nodeId?: string | null;
  workspaceRootRef?: string | null;
  workspaceRootHash?: string | null;
  workspaceRootLabel?: string | null;
  mdtodoRootRef?: string | null;
  hwpodWorkspaceArgs?: string | null;
  contextFingerprint?: string | null;
  providerProfile?: string | null;
  capabilities?: Record<string, unknown>;
  executionContext?: WorkbenchLaunchExecutionContext | null;
  bodyPreview: string;
  reportLinks: { linkId?: string; label?: string; href?: string; relativePath?: string | null }[];
}

export interface WorkbenchLaunchExecutionContext {
  sourceId?: string | null;
  sourceKind?: string | null;
  projectId?: string | null;
  taskRef?: string | null;
  fileRef?: string | null;
  relativePath?: string | null;
  taskId?: string | null;
  hwpodId?: string | null;
  nodeId?: string | null;
  workspaceRootRef?: string | null;
  workspaceRootHash?: string | null;
  workspaceRootLabel?: string | null;
  mdtodoRootRef?: string | null;
  hwpodWorkspaceArgs?: string | null;
  contextFingerprint?: string | null;
  capabilities?: Record<string, unknown>;
  valuesRedacted?: boolean;
}

/**
 * Launches a Workbench session through the public Workbench Launch API and seeds
 * it with a first-round user message built from the MDTODO task context. An empty
 * session is never treated as success: the launch must return a sessionId and the
 * session must project a first user message before navigation. MDTODO and
 * Workbench relate only via public API and IDs.
 */
export function useMdtodoWorkbenchLaunch(router: Router) {
  const launchLoading = ref(false);
  const launchError = ref<string | null>(null);
  const launchApiError = ref<ApiError | null>(null);
  const launchDiagnostic = ref<ErrorDiagnostic | null>(null);
  const launchResult = ref<{ sessionId: string; workbenchUrl: string } | null>(null);

  function setLaunchError(error: string | null, apiError: ApiError | null = null, diagnostic: ErrorDiagnostic | null = null): void {
    launchError.value = error;
    launchApiError.value = apiError;
    launchDiagnostic.value = diagnostic;
  }

  function buildPrompt(task: MdtodoTaskRecord, body: string, links: MdtodoTaskLinkRecord[], fileName: string, launchContext?: WorkbenchLaunchContext | null): string {
    const reportLines = links
      .filter((link) => link.kind === "markdown-report")
      .map((link) => `- ${link.label || link.href}: ${link.relativePath || link.href}`)
      .join("\n");
    const execution = launchContext?.executionContext ?? launchContext ?? null;
    const hwpodLines = execution?.hwpodId && execution?.hwpodWorkspaceArgs
      ? [
          "",
          "HWPOD 执行上下文:",
          `sourceId: ${execution.sourceId || launchContext?.sourceId || "-"}`,
          `hwpodId: ${execution.hwpodId}`,
          `nodeId: ${execution.nodeId || "-"}`,
          `mdtodoRootRef: ${execution.mdtodoRootRef || "docs/MDTODO"}`,
          `hwpodWorkspaceArgs: ${execution.hwpodWorkspaceArgs}`,
          "所有 hwpod/hwpod-ctl 命令都必须携带 hwpodWorkspaceArgs。读取 MDTODO、报告和工程文件必须使用 HWPOD workspace/node-ops 入口，不得猜本地容器路径或创建本地 .hwlab/hwpod-spec.yaml fallback。"
        ]
      : [];
    return [
      "请基于以下 MDTODO 任务开始工作，先读取相关文件和报告，再给出下一步执行结果。",
      "",
      `Task: ${task.taskId || task.taskRef} ${task.title || ""}`.trim(),
      `TaskRef: ${task.taskRef}`,
      `File: ${fileName || task.fileRef || "-"}`,
      `Status: ${task.status || "open"}`,
      "",
      "任务正文:",
      body.trim() || "(无正文)",
      "",
      "相关报告链接:",
      reportLines || "(无)",
      ...hwpodLines
    ].join("\n");
  }

  function buildContext(task: MdtodoTaskRecord, body: string, links: MdtodoTaskLinkRecord[], fileName: string): WorkbenchLaunchContext {
    return {
      source: "mdtodo-page",
      projectId: task.projectId || "",
      taskRef: task.taskRef,
      sourceId: task.sourceId,
      fileRef: task.fileRef,
      fileName,
      taskId: task.taskId,
      title: task.title,
      status: task.status,
      bodyPreview: body.slice(0, 800),
      reportLinks: links.filter((link) => link.kind === "markdown-report").map((link) => ({ linkId: link.linkId, label: link.label, href: link.href, relativePath: link.relativePath }))
    };
  }

  async function waitSessionHasPrompt(sessionId: string): Promise<void> {
    for (let attempt = 0; attempt < 5; attempt += 1) {
      const response = await workbenchAPI.session(sessionId, 8000);
      if (response.ok) {
        const session = response.data?.session as { messageCount?: number; messages?: unknown[]; firstUserMessagePreview?: string | null } | undefined;
        const count = Number(session?.messageCount ?? (Array.isArray(session?.messages) ? session.messages.length : 0));
        if (count > 0 || String(session?.firstUserMessagePreview ?? "").trim()) return;
      }
      await sleep(800);
    }
    throw new Error("Workbench session 已创建但未投影 MDTODO prompt");
  }

  function sleep(ms: number): Promise<void> {
    return new Promise((resolve) => window.setTimeout(resolve, ms));
  }

  async function launchTask(
    task: MdtodoTaskRecord,
    body: string,
    links: MdtodoTaskLinkRecord[],
    fileName: string,
    navigation: ProjectNavigationResponse | null,
    providerProfile: string
  ): Promise<{ sessionId: string; workbenchUrl: string } | null> {
    if (!task.taskRef || !task.projectId) return null;
    const enabled = navigation?.navigation?.capabilities?.workbenchLaunch === true;
    if (!enabled) {
      setLaunchError("Workbench Launch capability unavailable");
      return null;
    }
    const selectedProviderProfile = providerProfile.trim();
    if (!selectedProviderProfile) {
      setLaunchError("模型通道未选择");
      return null;
    }
    launchLoading.value = true;
    setLaunchError(null);
    try {
      const launchContext = { ...buildContext(task, body, links, fileName), providerProfile: selectedProviderProfile };
      const response = await workbenchAPI.launch({
        projectId: task.projectId,
        taskRef: task.taskRef,
        providerProfile: selectedProviderProfile,
        launchContext
      });
      if (!response.ok) throw response;
      const sessionId = response.data?.sessionId;
      if (!sessionId) throw new Error("Workbench launch 未返回 sessionId");
      const authoritativeLaunchContext = (response.data?.launchContext as WorkbenchLaunchContext | null | undefined) ?? launchContext;
      const prompt = buildPrompt(task, body, links, fileName, authoritativeLaunchContext);
      const chat = await agentAPI.sendAgentMessage({
        message: prompt,
        prompt,
        sessionId,
        providerProfile: selectedProviderProfile,
        projectId: task.projectId,
        taskRef: task.taskRef,
        launchContext: authoritativeLaunchContext
      }, 120000);
      if (!chat.ok) throw chat;
      await waitSessionHasPrompt(sessionId);
      const result = { sessionId, workbenchUrl: response.data?.workbenchUrl || `/workbench/sessions/${encodeURIComponent(sessionId)}` };
      launchResult.value = result;
      return result;
    } catch (err) {
      const context = apiErrorContextFromUnknown(err, "Workbench launch 失败");
      setLaunchError(context.error || "Workbench launch 失败", context.apiError, context.diagnostic);
      return null;
    } finally {
      launchLoading.value = false;
    }
  }

  async function navigateToWorkbench(result: { sessionId: string; workbenchUrl: string }): Promise<void> {
    await router.push(result.workbenchUrl);
  }

  function openWorkbenchTarget(): Window | null {
    const target = window.open("", "_blank");
    if (!target) return null;
    target.opener = null;
    target.document.title = "正在启动 Workbench";
    target.document.body.textContent = "正在启动 Workbench…";
    return target;
  }

  async function navigatePreparedTarget(result: { sessionId: string; workbenchUrl: string }, target: Window | null): Promise<void> {
    if (!target || target.closed) {
      await navigateToWorkbench(result);
      return;
    }
    target.location.assign(result.workbenchUrl);
  }

  function closeWorkbenchTarget(target: Window | null): void {
    if (target && !target.closed) target.close();
  }

  function isLaunchEnabled(navigation: ProjectNavigationResponse | null): boolean {
    return navigation?.navigation?.capabilities?.workbenchLaunch === true;
  }

  return {
    launchLoading,
    launchError,
    launchApiError,
    launchDiagnostic,
    launchResult,
    buildPrompt,
    buildContext,
    launchTask,
    navigateToWorkbench,
    openWorkbenchTarget,
    navigatePreparedTarget,
    closeWorkbenchTarget,
    isLaunchEnabled
  };
}

