import { z } from 'zod';
import type { ToolDef, ToolContext } from './types.js';
import { applyAll } from '../pending_changes.js';

const ApplyPendingInput = z.object({});
type ApplyPendingInputT = z.infer<typeof ApplyPendingInput>;

export const applyPendingTool: ToolDef<ApplyPendingInputT> = {
  name: 'apply_pending',
  description:
    'Apply all pending changes for the current session to disk. ' +
    'Each queued create/edit/delete is executed in order.',
  inputSchema: ApplyPendingInput,
  jsonSchema: {
    type: 'function',
    function: {
      name: 'apply_pending',
      description:
        'Apply all pending changes for the current session to disk. ' +
        'Each queued create/edit/delete is executed in order.',
      parameters: {
        type: 'object',
        properties: {},
        required: [],
      },
    },
  },
  async execute(_input: ApplyPendingInputT, projectRoot: string, context: ToolContext): Promise<unknown> {
    // Under Ask (and Plan) the human approves via the Pending Changes panel — the
    // agent must not auto-apply. Bypass and legacy (undefined) may apply.
    if (context.permissionMode === 'ask' || context.permissionMode === 'plan') {
      return {
        status: 'denied',
        message:
          'Permission mode is Ask — staged changes must be approved by the user in the Pending Changes panel, not applied by the agent.',
      };
    }
    const results = await applyAll(context.sql, context.sessionId, projectRoot);
    const succeeded = results.filter((r) => r.success).length;
    const failed = results.filter((r) => !r.success).length;

    return {
      total: results.length,
      succeeded,
      failed,
      results,
      message:
        results.length === 0
          ? 'No pending changes to apply.'
          : `Applied ${succeeded}/${results.length} changes.${failed > 0 ? ` ${failed} failed.` : ''}`,
    };
  },
};
