import type { CapabilityRequest } from "@best-agent/protocol";

export const SHELL_APPROVAL_DISPLAY_MAX_CHARS = 2048;

export function renderShellArgvForHistory(argv: readonly string[]): string {
  const safeArgv = redactShellArgvForHistory(argv);
  const text = safeArgv.join(" ");
  if (text.length <= SHELL_APPROVAL_DISPLAY_MAX_CHARS && !text.includes("\n")) {
    return text;
  }
  const rawText = argv.join(" ");
  return `[shell command omitted: ${rawText.length} chars, ${Buffer.byteLength(rawText, "utf8")} bytes]`;
}

export function redactSecretLikeTextForHistory(text: string): string {
  return text
    .replace(
      /\b(Authorization|X-API-Key|API-Key|API_KEY|Access-Token|AccessToken)(\s*[:=]\s*)(['"]?)(Bearer|Basic|Token)\s+[^'"\s]{6,}/giu,
      "$1$2$3$4 [secret-redacted]",
    )
    .replace(
      /\b(Authorization|X-API-Key|API-Key|API_KEY|Access-Token|AccessToken)(\s*[:=]\s*)(['"]?)(?!Bearer\b|Basic\b|Token\b)[^'"\s]{6,}/giu,
      "$1$2$3[secret-redacted]",
    )
    .replace(/\bBearer\s+[A-Za-z0-9._~+/-]{8,}\b/giu, "Bearer [secret-redacted]")
    .replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu, "[secret-redacted]")
    .replace(/\b[A-Za-z0-9+/=_-]{40,}\b/gu, "[long-token-redacted]");
}

const SPLIT_SECRET_HEADER_RE =
  /\b(?:Authorization|X-API-Key|API-Key|API_KEY|Access-Token|AccessToken)\s*[:=]?\s*$/iu;
const SPLIT_AUTH_SCHEME_RE = /^(?:Bearer|Basic|Token)$/iu;
const SPLIT_SECRET_AUTH_HEADER_RE =
  /\b(?:Authorization|X-API-Key|API-Key|API_KEY|Access-Token|AccessToken)\s*[:=]?\s*(?:Bearer|Basic|Token)\s*$/iu;

export function redactShellArgvForHistory(argv: readonly string[]): string[] {
  const output = argv.map((arg) => redactSecretLikeTextForHistory(arg));

  for (let index = 0; index < output.length; index += 1) {
    const current = output[index] ?? "";
    const next = output[index + 1] ?? "";
    const afterNext = output[index + 2] ?? "";

    if (SPLIT_SECRET_HEADER_RE.test(current)) {
      if (SPLIT_AUTH_SCHEME_RE.test(next)) {
        if (afterNext.length >= 6 && !afterNext.includes(" ")) {
          output[index + 2] = "[secret-redacted]";
        }
        continue;
      }

      if (next.length >= 6 && !next.includes(" ")) {
        output[index + 1] = "[secret-redacted]";
      }
    }

    if (SPLIT_SECRET_AUTH_HEADER_RE.test(current) && next.length >= 6 && !next.includes(" ")) {
      output[index + 1] = "[secret-redacted]";
    }
  }

  return output;
}

export function looksSecretLikeTextForHistory(value: string): boolean {
  return redactSecretLikeTextForHistory(value) !== value;
}

export function renderApprovalReasonForHistory(reason: string | undefined): string | undefined {
  if (reason === undefined) {
    return undefined;
  }
  if (reason.length <= SHELL_APPROVAL_DISPLAY_MAX_CHARS && !reason.includes("\n")) {
    return redactSecretLikeTextForHistory(reason);
  }
  return `[approval reason omitted: ${reason.length} chars, ${Buffer.byteLength(
    reason,
    "utf8",
  )} bytes]`;
}

export function toHistorySafeCapabilityRequest(request: CapabilityRequest): CapabilityRequest {
  const reason = renderApprovalReasonForHistory(request.reason);
  if (request.group !== "shell") {
    if (request.group === "network") {
      return {
        ...request,
        host: redactSecretLikeTextForHistory(request.host),
        ...(reason !== undefined ? { reason } : {}),
      };
    }
    if (request.group === "filesystem") {
      return {
        ...request,
        path: redactSecretLikeTextForHistory(request.path),
        ...(request.roots
          ? { roots: request.roots.map((root) => redactSecretLikeTextForHistory(root)) }
          : {}),
        ...(reason !== undefined ? { reason } : {}),
      };
    }
    return {
      ...request,
      ...(reason !== undefined ? { reason } : {}),
    };
  }
  const text = request.argv.join(" ");
  if (text.length <= SHELL_APPROVAL_DISPLAY_MAX_CHARS && !text.includes("\n")) {
    return {
      ...request,
      argv: redactShellArgvForHistory(request.argv),
      ...(reason !== undefined ? { reason } : {}),
    };
  }
  return {
    ...request,
    argv: [
      "[shell command omitted:",
      `${text.length} chars,`,
      `${Buffer.byteLength(text, "utf8")} bytes]`,
    ],
    ...(reason !== undefined ? { reason } : {}),
  };
}

export function summarizeCapabilityRequestForHistory(request: CapabilityRequest): string {
  switch (request.group) {
    case "shell":
      return `Command: ${renderShellArgvForHistory(request.argv)}`;
    case "network":
      return `Host: ${redactSecretLikeTextForHistory(request.host)}`;
    case "filesystem":
      return `${request.action === "read" ? "Read" : "Write"} path: ${redactSecretLikeTextForHistory(request.path)}`;
    case "tool":
      return `Tool: ${request.toolName}`;
    default:
      return "Capability request";
  }
}
