'use strict';

const SHELL_SIDE_EFFECT_RULES = [
  {
    domain: 'calendar',
    operation: 'create_event',
    recommendedTool: 'calendar_create',
    reason: 'Calendar event creation must use calendar_create so account, calendar, approval, and verification are tracked.',
    patterns: [
      /\bgws\b[\s\S]*\bcalendar\b[\s\S]*\bevents?\b[\s\S]*\binsert\b/i,
      /calendar\.googleapis\.com[\s\S]*\/events/i,
      /osascript[\s\S]*(?:tell\s+application\s+"Calendar"|Application\(["']Calendar["']\))[\s\S]*(?:make\s+new\s+event|events\.push|new\s+event\s+with\s+properties)/i,
      /(?:tell\s+application\s+"Calendar"|Application\(["']Calendar["']\))[\s\S]*(?:make\s+new\s+event|events\.push|new\s+event\s+with\s+properties)/i,
    ],
  },
  {
    domain: 'email',
    operation: 'send_email',
    recommendedTool: 'mail_send or mail_reply',
    reason: 'Email dispatch must use mail_send or mail_reply so recipients, threading, approval, and sent-mail verification are tracked.',
    patterns: [
      /\bgws\b[\s\S]*\bgmail\b[\s\S]*(?:\+send|messages\s+send|users\s+messages\s+send)\b/i,
      /gmail\.googleapis\.com[\s\S]*\/messages\/send\b/i,
      /osascript[\s\S]*(?:tell\s+application\s+"Mail"|Application\(["']Mail["']\))[\s\S]*(?:make\s+new\s+outgoing\s+message|send\b)/i,
      /(?:tell\s+application\s+"Mail"|Application\(["']Mail["']\))[\s\S]*(?:make\s+new\s+outgoing\s+message|send\b)/i,
    ],
  },
  {
    domain: 'slack',
    operation: 'send_message',
    recommendedTool: 'slack_send_message',
    reason: 'Slack message dispatch must use slack_send_message so channel, approval, and execution evidence are tracked.',
    patterns: [
      /slack\.com\/api\/chat\.postMessage/i,
      /\bslack\b[\s\S]*\bchat\.postMessage\b/i,
    ],
  },
  {
    domain: 'reminder',
    operation: 'create_reminder',
    recommendedTool: 'reminder_create',
    reason: 'Reminder creation must use reminder_create so approval and execution evidence are tracked.',
    patterns: [
      /osascript[\s\S]*(?:tell\s+application\s+"Reminders"|Application\(["']Reminders["']\))[\s\S]*(?:make\s+new\s+reminder|new\s+reminder)/i,
      /(?:tell\s+application\s+"Reminders"|Application\(["']Reminders["']\))[\s\S]*(?:make\s+new\s+reminder|new\s+reminder)/i,
    ],
  },
];

const MCP_SIDE_EFFECT_RULES = [
  {
    domain: 'calendar',
    operation: 'create_event',
    recommendedTool: 'calendar_create',
    pattern: /(?:calendar|google[-_ ]?calendar).*?(?:create|insert|add|schedule)|(?:create|insert|add|schedule).*?(?:calendar|event)/i,
  },
  {
    domain: 'email',
    operation: 'send_email',
    recommendedTool: 'mail_send or mail_reply',
    pattern: /(?:gmail|mail|email).*?(?:send|reply|respond)|(?:send|reply|respond).*?(?:gmail|mail|email)/i,
  },
  {
    domain: 'slack',
    operation: 'send_message',
    recommendedTool: 'slack_send_message',
    pattern: /(?:slack).*?(?:send|post|message)|(?:send|post).*?(?:slack|channel)/i,
  },
];

function commandText(input = {}) {
  if (!input || typeof input !== 'object') return '';
  if (typeof input.command === 'string') {
    const args = Array.isArray(input.args) && input.args.length ? ` ${input.args.join(' ')}` : '';
    return `${input.command}${args}`;
  }
  if (typeof input.script === 'string') return input.script;
  return '';
}

function classifyExternalActionBypass(toolName, input = {}) {
  const name = String(toolName || '').trim();
  if (name === 'run_shell' || name === 'shell' || name === 'bash' || name === 'terminal' || name === 'applescript') {
    const text = commandText(input);
    if (!text) return null;
    for (const rule of SHELL_SIDE_EFFECT_RULES) {
      if (rule.patterns.some((pattern) => pattern.test(text))) {
        return {
          toolName: name,
          domain: rule.domain,
          operation: rule.operation,
          recommendedTool: rule.recommendedTool,
          reason: rule.reason,
          evidence: text.slice(0, 500),
        };
      }
    }
  }

  if (name === 'mcp_call' || name.startsWith('mcp__')) {
    const callName = name === 'mcp_call'
      ? `${input.server || ''}.${input.tool || ''}`
      : name;
    const text = `${callName} ${JSON.stringify(input.arguments || input.args || {})}`.slice(0, 1000);
    for (const rule of MCP_SIDE_EFFECT_RULES) {
      if (rule.pattern.test(text)) {
        return {
          toolName: name,
          domain: rule.domain,
          operation: rule.operation,
          recommendedTool: rule.recommendedTool,
          reason: `MCP side-effect tools must be routed through ${rule.recommendedTool} so approval and verification are tracked.`,
          evidence: text.slice(0, 500),
        };
      }
    }
  }

  return null;
}

function buildGatewayBlockedResult(finding) {
  return {
    external_action: true,
    external_action_gateway: true,
    blocked: true,
    executed: false,
    verified: false,
    decision: 'dedicated_tool_required',
    domain: finding.domain,
    operation: finding.operation,
    original_tool: finding.toolName,
    recommended_tool: finding.recommendedTool,
    reason: finding.reason,
    evidence: finding.evidence,
    approval_policy: {
      kind: 'external_action',
      allow_always: false,
      approval_scope: 'exact_action_payload',
    },
    model_instruction: [
      `Do not retry this ${finding.domain} side effect through ${finding.toolName}.`,
      `Use ${finding.recommendedTool} instead so Wall-E can stage an exact approval envelope, execute the approved payload, and verify the result before summarizing success.`,
      'Do not claim this action was executed.',
    ].join(' '),
  };
}

function reviewExternalActionGateway({ toolName, input = {} } = {}) {
  const finding = classifyExternalActionBypass(toolName, input);
  if (!finding) return { admitted: true };
  return {
    admitted: false,
    finding,
    result: buildGatewayBlockedResult(finding),
  };
}

module.exports = {
  buildGatewayBlockedResult,
  classifyExternalActionBypass,
  reviewExternalActionGateway,
};
