/**
 * Mock implementation of Tauri invoke for testing
 */

export interface InvokeCall {
  command: string;
  args: Record<string, any>;
}

let invokeHistory: InvokeCall[] = [];
let invokeResponses: Map<string, any> = new Map();

/**
 * Mock invoke function that captures calls
 */
export const mockInvoke = async (
  command: string,
  args?: Record<string, any>
): Promise<any> => {
  const callArgs = args || {};
  invokeHistory.push({ command, args: callArgs });

  // Return mock response if set
  const response = invokeResponses.get(command);
  if (response !== undefined) {
    if (response instanceof Error) {
      throw response;
    }
    return response;
  }

  // Default success response
  return { success: true };
};

/**
 * Set a mock response for a command
 */
export const setMockResponse = (command: string, response: any): void => {
  invokeResponses.set(command, response);
};

/**
 * Get all invoke calls made during test
 */
export const getInvokeCalls = (): InvokeCall[] => {
  return [...invokeHistory];
};

/**
 * Get calls for a specific command
 */
export const getInvokeCalls_ForCommand = (command: string): InvokeCall[] => {
  return invokeHistory.filter((call) => call.command === command);
};

/**
 * Get the last invoke call
 */
export const getLastInvokeCall = (): InvokeCall | undefined => {
  return invokeHistory[invokeHistory.length - 1];
};

/**
 * Clear invoke history
 */
export const clearInvokeHistory = (): void => {
  invokeHistory = [];
  invokeResponses.clear();
};

/**
 * Verify a command was called with expected parameters
 */
export const expectInvokeCall = (
  command: string,
  expectedArgs: Record<string, any>
): void => {
  const calls = getInvokeCalls_ForCommand(command);

  if (calls.length === 0) {
    throw new Error(`Command "${command}" was never called`);
  }

  const lastCall = calls[calls.length - 1];

  // Deep equality check
  for (const [key, expectedValue] of Object.entries(expectedArgs)) {
    const actualValue = lastCall.args[key];

    if (JSON.stringify(actualValue) !== JSON.stringify(expectedValue)) {
      throw new Error(
        `Parameter "${key}" mismatch:\n` +
          `  Expected: ${JSON.stringify(expectedValue)}\n` +
          `  Actual: ${JSON.stringify(actualValue)}`
      );
    }
  }
};

/**
 * Helper to get parameter value from invoke calls
 */
export const getInvokeParameter = (
  command: string,
  paramName: string,
  callIndex = -1 // -1 = last call
): any => {
  const calls = getInvokeCalls_ForCommand(command);

  if (calls.length === 0) {
    throw new Error(`Command "${command}" was never called`);
  }

  const targetCall = callIndex === -1 ? calls[calls.length - 1] : calls[callIndex];
  return targetCall.args[paramName];
};
