'use strict';

const HOOK_MANIFEST = 'walle-hook.json';
const MAX_HOOK_MANIFEST_BYTES = 128 * 1024;

const HOOK_EVENTS = Object.freeze([
  'before_prompt_build',
  'llm_input',
  'llm_output',
  'agent_end',
  'tool_result',
  'session_patch',
  'message_received',
  'message_sent',
]);

const HOOK_EVENT_ALIASES = Object.freeze({
  'run.before': 'before_prompt_build',
  'prompt.before_build': 'before_prompt_build',
  'llm.input': 'llm_input',
  'llm.output': 'llm_output',
  'agent.end': 'agent_end',
  'tool.after': 'tool_result',
  'tool.result': 'tool_result',
  'session.patch': 'session_patch',
  'message.received': 'message_received',
  'message.sent': 'message_sent',
});

function normalizeHookEvent(event) {
  const value = String(event || '').trim();
  return HOOK_EVENT_ALIASES[value] || value;
}

function validateHookManifest(manifest = {}, { packageDir = '' } = {}) {
  const errors = [];
  if (!manifest.id || typeof manifest.id !== 'string') errors.push('id is required');
  if (manifest.id && !/^[a-z0-9][a-z0-9._-]*$/i.test(manifest.id)) errors.push('id has invalid characters');
  if (!manifest.entry || typeof manifest.entry !== 'string') errors.push('entry is required');
  if (manifest.entry && (manifest.entry.includes('..') || manifest.entry.startsWith('/') || manifest.entry.includes('\\'))) {
    errors.push('entry must be a relative path inside the hook package');
  }
  const rawEvents = Array.isArray(manifest.events) ? manifest.events : [];
  const events = [];
  if (rawEvents.length === 0) errors.push('events must include at least one supported event');
  for (const event of rawEvents) {
    const normalized = normalizeHookEvent(event);
    if (!HOOK_EVENTS.includes(normalized)) {
      errors.push(`unsupported event: ${event}`);
    } else if (!events.includes(normalized)) {
      events.push(normalized);
    }
  }
  const permissions = manifest.permissions || {};
  for (const key of Object.keys(permissions)) {
    if (typeof permissions[key] !== 'boolean') errors.push(`permission ${key} must be boolean`);
  }

  return {
    ok: errors.length === 0,
    errors,
    manifest: {
      id: manifest.id || '',
      version: manifest.version || '0.0.0',
      events,
      entry: manifest.entry || '',
      permissions,
      packageDir,
      metadata: { ...(manifest.metadata || {}) },
    },
  };
}

module.exports = {
  HOOK_EVENTS,
  HOOK_EVENT_ALIASES,
  HOOK_MANIFEST,
  MAX_HOOK_MANIFEST_BYTES,
  normalizeHookEvent,
  validateHookManifest,
};
