import { BestAgentError } from "@best-agent/foundation";
import type { ToolInputValue, WorkflowName, WorkflowPhaseName } from "@best-agent/protocol";
import { z } from "zod";
import { DELEGATE_TASKS_TOOL_NAME } from "../../provider/provider-tool-names.js";
import { getToolInputJsonSchema, parseZodToolInput, toolInputSchema } from "../../tool/schema.js";

const DELEGATE_TASK_SCHEMA = z.strictObject({
  goal: z.string().optional(),
  profileName: z.string().optional(),
  subagentType: z.enum(["explore", "plan", "build", "verify"]).default("explore"),
});

const DELEGATE_TASKS_TOOL_INPUT_ZOD_SCHEMA = toolInputSchema(
  z.strictObject({
    goal: z.string().optional(),
    profileName: z.string().optional(),
    subagentType: z.enum(["explore", "plan", "build", "verify"]).default("explore"),
    tasks: z.array(DELEGATE_TASK_SCHEMA).optional(),
  }),
);

export const DELEGATE_TASKS_TOOL_INPUT_SCHEMA = getToolInputJsonSchema(
  DELEGATE_TASKS_TOOL_INPUT_ZOD_SCHEMA,
) as Record<string, unknown>;

export const DELEGATE_TASKS_TOOL_DESCRIPTION =
  'Delegate one or more focused subtasks to child threads. Use {"goal":"...","subagentType":"explore|plan|build|verify"} or {"tasks":[...]} with optional profileName overrides.';

export function normalizeDelegateTasksInput(input: ToolInputValue): {
  tasks: Array<{
    goal: string;
    profileName?: string;
    subagentType: WorkflowPhaseName;
  }>;
} {
  const record = parseZodToolInput(
    DELEGATE_TASKS_TOOL_NAME,
    DELEGATE_TASKS_TOOL_INPUT_ZOD_SCHEMA,
    input,
  ) as Record<string, unknown>;
  const tasksCandidate = Array.isArray(record.tasks) ? record.tasks : undefined;
  if (tasksCandidate && tasksCandidate.length > 0) {
    return {
      tasks: tasksCandidate.map((candidate) =>
        normalizeDelegateTaskRecord(candidate as ToolInputValue),
      ),
    };
  }

  return {
    tasks: [normalizeDelegateTaskRecord(record as ToolInputValue)],
  };
}

export function serializeDelegateTasksInput(
  input: ReturnType<typeof normalizeDelegateTasksInput>,
): ToolInputValue {
  if (input.tasks.length === 1) {
    return {
      goal: input.tasks[0].goal,
      ...(input.tasks[0].profileName ? { profileName: input.tasks[0].profileName } : {}),
      subagentType: input.tasks[0].subagentType,
    };
  }

  return {
    tasks: input.tasks.map((task) => ({
      goal: task.goal,
      ...(task.profileName ? { profileName: task.profileName } : {}),
      subagentType: task.subagentType,
    })),
  };
}

export function workflowNameForDelegateSubagent(subagentType: WorkflowPhaseName): WorkflowName {
  switch (subagentType) {
    case "plan":
      return "plan-build-verify";
    case "explore":
      return "explore-build";
    case "build":
    case "verify":
      return "build-verify";
  }
}

export function stripChildPersistenceDirectives(objective: string): string {
  return objective
    .trim()
    .replace(
      /[，,]?\s*用\s*(?:write-scratch|append-scratch)\s*写入[^。\n]*/giu,
      "，将分析结果返回给父线程",
    )
    .replace(
      /[，,]?\s*使用\s*(?:write-scratch|append-scratch)[^。\n]*/giu,
      "，将分析结果返回给父线程",
    )
    .replace(
      /[，,]?\s*(?:将)?(?:分析结果|结果|输出)?(?:写入|写到|保存到|保存为|持久化到)\s*(?:scratch|workspace)\s*文件[^。\n]*/giu,
      "，将分析结果返回给父线程",
    )
    .replace(
      /[，,]?\s*(?:将)?(?:分析结果|结果|输出)?(?:写入|写到|保存到|保存为|持久化到)\s*[^。\n]*\b(?:scratch|workspace)\b[^。\n]*/giu,
      "，将分析结果返回给父线程",
    )
    .replace(
      /\buse\s+(?:write-scratch|append-scratch)\b[^.\n]*/gi,
      "return the analysis to the parent thread",
    )
    .replace(
      /(?<!do not )\b(?:write|save|persist)\b[^.\n]*\b(?:scratch|workspace)\b[^.\n]*/gi,
      "return the analysis to the parent thread",
    )
    .replace(/[ \t]+\n/g, "\n")
    .replace(/\n{3,}/g, "\n\n")
    .trim();
}

function normalizeDelegateTaskRecord(input: ToolInputValue): {
  goal: string;
  profileName?: string;
  subagentType: WorkflowPhaseName;
} {
  if (!input || typeof input !== "object" || Array.isArray(input)) {
    throw new BestAgentError("TOOL_INPUT_INVALID", "delegate_tasks task entries must be objects.");
  }

  const record = input as Record<string, unknown>;
  const goalCandidate = typeof record.goal === "string" ? record.goal : "";
  const goal = stripChildPersistenceDirectives(goalCandidate).trim();
  if (!goal) {
    throw new BestAgentError("TOOL_INPUT_INVALID", "delegate_tasks requires a non-empty goal.");
  }

  const profileNameCandidate =
    typeof record.profileName === "string" ? record.profileName.trim() : "";
  const profileName = profileNameCandidate || undefined;

  return {
    goal,
    ...(profileName ? { profileName } : {}),
    subagentType: readDelegateSubagentType(record.subagentType),
  };
}

function readDelegateSubagentType(value: unknown): WorkflowPhaseName {
  if (value === "explore" || value === "plan" || value === "build" || value === "verify") {
    return value;
  }
  throw new BestAgentError("TOOL_INPUT_INVALID", "delegate_tasks requires a valid subagentType.");
}
