import type { AgentRunMode } from "./AgentSdkAdapter.ts";
import { isLeaderRoleAgentId } from "../skill/FcopToolProfile.ts";
import {
  isAdminRejectColdPathPrompt,
  isPmSelfExecuteHotPathPrompt,
  isPmSelfReportOnlyMode,
  isRuntimeTaskDispatchPrompt,
  resolveGeminiToolSelectionMode,
  selectGeminiToolNames,
  type GeminiToolSelectionMode,
} from "./geminiToolSelection.ts";

/** Google FCoP-first tool exposure modes (CODEFLOW_GOOGLE_TOOL_MODE). */
export type GoogleToolMode =
  | "fcop_minimal"
  | "workspace_read"
  | "profile"
  | "trim"
  | "full";

export const GOOGLE_TOOL_MODE_ENV = "CODEFLOW_GOOGLE_TOOL_MODE";
export const GEMINI_TOOL_MODE_ENV_LEGACY = "CODEFLOW_GEMINI_TOOL_MODE";

export const FCOP_MINIMAL_CORE_TOOLS = [
  "read_task",
  "list_tasks",
  "claim_task",
  "write_report",
  "submit_task",
] as const;

export const WORKSPACE_READ_TOOLS = [
  "read_file",
  "grep_files",
  "list_dir",
  "web_search",
  "web_extract",
  "web_research",
  "skill_search",
  "skill_learn",
] as const;

export const VISION_INSPECT_ATTACHMENT_TOOL = "vision.inspect_attachment";

export const GOOGLE_DISPATCH_TOOLS = ["write_task", "create_task"] as const;

const VALID_GOOGLE_TOOL_MODES = new Set<string>([
  "fcop_minimal",
  "workspace_read",
  "profile",
  "trim",
  "full",
]);

function normalizeEnvValue(value: string | undefined): string {
  return (value ?? "").trim().toLowerCase();
}

/**
 * Resolve Google tool mode — `CODEFLOW_GOOGLE_TOOL_MODE` wins over legacy
 * `CODEFLOW_GEMINI_TOOL_MODE` (profile/trim/full only).
 */
export function resolveGoogleToolMode(
  env: NodeJS.ProcessEnv = process.env,
): GoogleToolMode {
  const googleRaw = normalizeEnvValue(env[GOOGLE_TOOL_MODE_ENV]);
  if (googleRaw) {
    if (VALID_GOOGLE_TOOL_MODES.has(googleRaw)) {
      return googleRaw as GoogleToolMode;
    }
    return "fcop_minimal";
  }

  const legacy = resolveGeminiToolSelectionMode(env[GEMINI_TOOL_MODE_ENV_LEGACY]);
  return legacy as GoogleToolMode;
}

export type GoogleDispatchContext = {
  agentId?: string;
  promptText?: string;
  runMode?: AgentRunMode;
};

/** PM / leader may dispatch downstream tasks only in explicit cold-path scenarios. */
export function isGoogleDispatchAllowed(ctx: GoogleDispatchContext): boolean {
  const agentId = ctx.agentId ?? "";
  const prompt = ctx.promptText ?? "";

  if (isPmSelfReportOnlyMode(prompt, agentId, ctx.runMode)) {
    return false;
  }

  if (!isLeaderRoleAgentId(agentId)) {
    return false;
  }

  if (isAdminRejectColdPathPrompt(prompt, agentId)) {
    return true;
  }

  if (isPmSelfExecuteHotPathPrompt(prompt, agentId)) {
    return false;
  }

  if (isRuntimeTaskDispatchPrompt(prompt)) {
    return false;
  }

  return true;
}

export type FilterGoogleToolsInput = {
  mode: GoogleToolMode;
  agentId?: string;
  allowedTools: readonly string[];
  promptText?: string;
  runMode?: AgentRunMode;
};

function baseToolsForMode(mode: GoogleToolMode): readonly string[] {
  switch (mode) {
    case "fcop_minimal":
      return FCOP_MINIMAL_CORE_TOOLS;
    case "workspace_read":
      return [...FCOP_MINIMAL_CORE_TOOLS, ...WORKSPACE_READ_TOOLS];
    case "profile":
    case "trim":
    case "full":
      return [];
    default:
      return FCOP_MINIMAL_CORE_TOOLS;
  }
}

function intersectAllowed(
  allowed: readonly string[],
  names: readonly string[],
): string[] {
  const set = new Set(allowed);
  return names.filter((n) => set.has(n));
}

/**
 * Filter exposed Gemini tool names by Google tool mode + PM dispatch policy.
 */
export function filterGoogleToolsByMode(input: FilterGoogleToolsInput): string[] {
  const allowed = input.allowedTools.map((n) => String(n).trim()).filter(Boolean);
  const mode = input.mode;
  const dispatchCtx: GoogleDispatchContext = {
    agentId: input.agentId,
    promptText: input.promptText,
    runMode: input.runMode,
  };

  let selected: string[];

  if (mode === "profile" || mode === "trim" || mode === "full") {
    selected = selectGeminiToolNames(
      allowed,
      input.promptText ?? "",
      input.agentId ?? "",
      { runMode: input.runMode },
    );
  } else {
    const base = baseToolsForMode(mode);
    selected = intersectAllowed(allowed.length > 0 ? allowed : [...base], base);
    if (
      allowed.includes(VISION_INSPECT_ATTACHMENT_TOOL) ||
      mode === "fcop_minimal" ||
      mode === "workspace_read"
    ) {
      if (!selected.includes(VISION_INSPECT_ATTACHMENT_TOOL)) {
        selected = [...selected, VISION_INSPECT_ATTACHMENT_TOOL];
      }
    }
  }

  if (!isGoogleDispatchAllowed(dispatchCtx)) {
    const blocked = new Set(GOOGLE_DISPATCH_TOOLS);
    selected = selected.filter((n) => !blocked.has(n as (typeof GOOGLE_DISPATCH_TOOLS)[number]));
  }

  return [...new Set(selected)];
}

/** Map GoogleToolMode to legacy Gemini selection mode when needed. */
export function googleModeToGeminiSelectionMode(
  mode: GoogleToolMode,
): GeminiToolSelectionMode | null {
  if (mode === "profile" || mode === "trim" || mode === "full") {
    return mode;
  }
  return null;
}
