/**
 * Codex Approval Handlers
 *
 * Pure functions that build PermissionRequest objects from Codex
 * JSON-RPC approval request parameters. Each function translates
 * the Codex-specific params into the browser-facing format.
 */

import { randomUUID } from "node:crypto";
import type { PermissionRequest } from "./session-types.js";

// ─── Approval Request Builders ────────────────────────────────────────────────

/** Build a PermissionRequest for a command execution approval. */
export function buildCommandApprovalRequest(
  params: Record<string, unknown>,
  executionCwd: string,
): { requestId: string; permission: PermissionRequest } {
  const requestId = `codex-approval-${randomUUID()}`;
  const command = params.command as string | string[] | undefined;
  const commandStr = params.parsedCmd as string || (Array.isArray(command) ? command.join(" ") : command) || "";

  return {
    requestId,
    permission: {
      request_id: requestId,
      tool_name: "Bash",
      input: {
        command: commandStr,
        cwd: params.cwd as string || executionCwd,
      },
      description: params.reason as string || `Execute: ${commandStr}`,
      tool_use_id: params.itemId as string || requestId,
      timestamp: Date.now(),
    },
  };
}

/** Build a PermissionRequest for a file change approval. */
export function buildFileChangeApprovalRequest(
  params: Record<string, unknown>,
): { requestId: string; permission: PermissionRequest } {
  const requestId = `codex-approval-${randomUUID()}`;
  const changes = params.changes as Array<{ path?: string; kind?: string }> | undefined;
  const filePaths = changes?.map((c) => c.path).filter(Boolean) || [];
  const fileList = filePaths.length > 0 ? filePaths.join(", ") : undefined;

  return {
    requestId,
    permission: {
      request_id: requestId,
      tool_name: "Edit",
      input: {
        description: params.reason as string || "File changes pending approval",
        ...(filePaths.length > 0 && { file_paths: filePaths }),
        ...(changes && { changes }),
      },
      description: params.reason as string || (fileList ? `Codex wants to modify: ${fileList}` : "Codex wants to modify files"),
      tool_use_id: params.itemId as string || requestId,
      timestamp: Date.now(),
    },
  };
}

/** Build a PermissionRequest for an MCP tool call approval. */
export function buildMcpToolCallApprovalRequest(
  params: Record<string, unknown>,
): { requestId: string; permission: PermissionRequest } {
  const requestId = `codex-approval-${randomUUID()}`;
  const server = params.server as string || "unknown";
  const tool = params.tool as string || "unknown";
  const args = params.arguments as Record<string, unknown> || {};

  return {
    requestId,
    permission: {
      request_id: requestId,
      tool_name: `mcp:${server}:${tool}`,
      input: args,
      description: params.reason as string || `MCP tool call: ${server}/${tool}`,
      tool_use_id: params.itemId as string || requestId,
      timestamp: Date.now(),
    },
  };
}

/** Build a PermissionRequest for a dynamic tool call. */
export function buildDynamicToolCallApprovalRequest(
  params: Record<string, unknown>,
  toolName: string,
  callId: string,
): { requestId: string; permission: PermissionRequest } {
  const requestId = `codex-dynamic-${randomUUID()}`;
  const toolArgs = params.arguments as Record<string, unknown> || {};

  return {
    requestId,
    permission: {
      request_id: requestId,
      tool_name: `dynamic:${toolName}`,
      input: {
        ...toolArgs,
        call_id: callId,
      },
      description: `Custom tool call: ${toolName}`,
      tool_use_id: callId,
      timestamp: Date.now(),
    },
  };
}

/** Build the response payload for a dynamic tool call approval/denial. */
export function buildDynamicToolCallResponse(
  msg: { behavior: "allow" | "deny"; updated_input?: Record<string, unknown> },
  toolName: string,
): { contentItems: unknown[]; success: boolean; structuredContent?: unknown } {
  if (msg.behavior === "deny") {
    return {
      contentItems: [{ type: "inputText", text: `Dynamic tool "${toolName}" was denied by user` }],
      success: false,
    };
  }

  const rawContentItems = msg.updated_input?.contentItems;
  const contentItems = Array.isArray(rawContentItems) && rawContentItems.length > 0
    ? rawContentItems
    : [{ type: "inputText", text: String(msg.updated_input?.text || "Dynamic tool call completed") }];

  const success = typeof msg.updated_input?.success === "boolean"
    ? msg.updated_input.success
    : true;

  const structuredContent = msg.updated_input?.structuredContent;

  return {
    contentItems,
    success,
    ...(structuredContent !== undefined ? { structuredContent } : {}),
  };
}

/** Build a PermissionRequest for a user input question. */
export function buildUserInputApprovalRequest(
  params: Record<string, unknown>,
): { requestId: string; questionIds: string[]; permission: PermissionRequest } {
  const requestId = `codex-userinput-${randomUUID()}`;

  const questions = params.questions as Array<{
    id: string; header: string; question: string;
    isOther: boolean; isSecret: boolean;
    options: Array<{ label: string; description: string }> | null;
  }> || [];

  return {
    requestId,
    questionIds: questions.map((q) => q.id),
    permission: {
      request_id: requestId,
      tool_name: "AskUserQuestion",
      input: {
        questions: questions.map((q) => ({
          header: q.header,
          question: q.question,
          options: q.options?.map((o) => ({ label: o.label, description: o.description })) || [],
        })),
      },
      description: questions[0]?.question || "User input requested",
      tool_use_id: params.itemId as string || requestId,
      timestamp: Date.now(),
    },
  };
}

/** Build a PermissionRequest for an apply-patch approval. */
export function buildApplyPatchApprovalRequest(
  params: Record<string, unknown>,
): { requestId: string; permission: PermissionRequest } {
  const requestId = `codex-patch-${randomUUID()}`;
  const fileChanges = params.fileChanges as Record<string, unknown> || {};
  const filePaths = Object.keys(fileChanges);
  const reason = params.reason as string | null;

  return {
    requestId,
    permission: {
      request_id: requestId,
      tool_name: "Edit",
      input: {
        file_paths: filePaths,
        ...(reason && { reason }),
      },
      description: reason || (filePaths.length > 0
        ? `Codex wants to modify: ${filePaths.join(", ")}`
        : "Codex wants to modify files"),
      tool_use_id: params.callId as string || requestId,
      timestamp: Date.now(),
    },
  };
}

/** Build a PermissionRequest for an exec-command approval. */
export function buildExecCommandApprovalRequest(
  params: Record<string, unknown>,
  executionCwd: string,
): { requestId: string; permission: PermissionRequest } {
  const requestId = `codex-exec-${randomUUID()}`;
  const command = params.command as string[] || [];
  const commandStr = command.join(" ");
  const cwd = params.cwd as string || executionCwd;
  const reason = params.reason as string | null;

  return {
    requestId,
    permission: {
      request_id: requestId,
      tool_name: "Bash",
      input: {
        command: commandStr,
        cwd,
      },
      description: reason || `Execute: ${commandStr}`,
      tool_use_id: params.callId as string || requestId,
      timestamp: Date.now(),
    },
  };
}
