import {
  classifyFcopToolOutcome,
  type ClassifiedToolOutcome,
} from "./FcopToolOutcome.ts";

const SUBMIT_ALREADY_IN_REVIEW_RE =
  /submit_review denied:\s*expected state active,\s*got review/i;

/** TASK 已在 review 时重复 submit — 幂等成功，不污染 runner failed。 */
export function isSubmitTaskAlreadySubmitted(output: string): boolean {
  const text = (output ?? "").trim();
  if (!text) return false;
  return (
    SUBMIT_ALREADY_IN_REVIEW_RE.test(text) ||
    /expected state active,\s*got review/i.test(text)
  );
}

export function classifyGoogleContractToolOutcome(
  toolName: string,
  output: string,
): ClassifiedToolOutcome {
  if (toolName === "submit_task" && isSubmitTaskAlreadySubmitted(output)) {
    return {
      outcome: "success",
      label: "成功（任务已在 review，重复 submit 幂等）",
    };
  }
  return classifyFcopToolOutcome(toolName, output);
}

export type GoogleContractStopReason =
  | "write_report_submit_done"
  | "invalid_agent_output"
  | "zero_toolcall"
  | "hit_max_rounds"
  | "function_response_misaligned"
  | "model_not_found"
  | "tool_failed"
  | "authority_denied";

export type GoogleContractState = {
  invalidAgentOutputStrikes: number;
  zeroToolcallStrikes: number;
  functionResponseMismatchStrikes: number;
  hadWriteReportSuccess: boolean;
  hadSubmitTaskSuccess: boolean;
  modelNotFound: boolean;
  hitMaxRounds: boolean;
  blocked: boolean;
  stopReason: GoogleContractStopReason | null;
};

export function createGoogleContractState(): GoogleContractState {
  return {
    invalidAgentOutputStrikes: 0,
    zeroToolcallStrikes: 0,
    functionResponseMismatchStrikes: 0,
    hadWriteReportSuccess: false,
    hadSubmitTaskSuccess: false,
    modelNotFound: false,
    hitMaxRounds: false,
    blocked: false,
    stopReason: null,
  };
}

export type RecordGoogleContractToolResultInput = {
  toolName: string;
  output: string;
  ok?: boolean;
};

export function recordGoogleContractToolResult(
  state: GoogleContractState,
  input: RecordGoogleContractToolResultInput,
): void {
  const toolName = String(input.toolName ?? "").trim();
  const output = String(input.output ?? "");
  const classified = classifyGoogleContractToolOutcome(toolName, output);
  const ok = input.ok !== false && classified.outcome === "success";

  if (toolName === "write_report" && ok) {
    state.hadWriteReportSuccess = true;
  }
  if (toolName === "submit_task" && ok) {
    state.hadSubmitTaskSuccess = true;
  }
}

export function recordGoogleContractZeroToolcall(
  state: GoogleContractState,
): void {
  state.zeroToolcallStrikes += 1;
  if (state.zeroToolcallStrikes >= 3) {
    markGoogleContractBlocked(state, "zero_toolcall");
  }
}

export function recordGoogleContractInvalidOutput(
  state: GoogleContractState,
): void {
  state.invalidAgentOutputStrikes += 1;
  if (state.invalidAgentOutputStrikes >= 2) {
    markGoogleContractBlocked(state, "invalid_agent_output");
  }
}

export function recordGoogleContractFrMismatch(
  state: GoogleContractState,
): void {
  state.functionResponseMismatchStrikes += 1;
  if (state.functionResponseMismatchStrikes >= 2) {
    markGoogleContractBlocked(state, "function_response_misaligned");
  }
}

export function recordGoogleContractModelNotFound(
  state: GoogleContractState,
): void {
  state.modelNotFound = true;
  markGoogleContractBlocked(state, "model_not_found");
}

export function recordGoogleContractHitMaxRounds(
  state: GoogleContractState,
): void {
  state.hitMaxRounds = true;
  markGoogleContractBlocked(state, "hit_max_rounds");
}

function markGoogleContractBlocked(
  state: GoogleContractState,
  reason: GoogleContractStopReason,
): void {
  state.blocked = true;
  state.stopReason = reason;
}

export type ShouldStopGoogleContractLoopInput = {
  state: GoogleContractState;
  /** When true, write_report + submit_task both succeeded — may end tool loop early. */
  allowEarlyStopOnReportSubmit?: boolean;
};

export function shouldStopGoogleContractLoop(
  input: ShouldStopGoogleContractLoopInput,
): boolean {
  const { state, allowEarlyStopOnReportSubmit = true } = input;

  if (state.blocked) {
    return true;
  }

  if (
    allowEarlyStopOnReportSubmit &&
    state.hadWriteReportSuccess &&
    state.hadSubmitTaskSuccess
  ) {
    state.stopReason = "write_report_submit_done";
    return true;
  }

  return false;
}
