'use strict';

const ScopeKind = Object.freeze({
  WORKSPACE: 'workspace',
  MODULE: 'module',
  SINGLE_FILE: 'single_file',
  CUSTOM: 'custom',
});

function createTaskPacket(input = {}) {
  const scopeInput = input.scope && typeof input.scope === 'object' ? input.scope : {};
  const scopeKind = normalizeScopeKind(scopeInput.kind || input.scopeKind || input.scope || ScopeKind.WORKSPACE);
  const scopePath = scopeInput.path || input.scopePath || input.scope_path || '';
  return {
    objective: String(input.objective || input.prompt || input.task || '').trim(),
    scope: {
      kind: scopeKind,
      path: String(scopePath || '').trim(),
      description: String(scopeInput.description || input.scopeDescription || '').trim(),
    },
    repo: String(input.repo || input.repository || '').trim(),
    worktree: String(input.worktree || input.cwd || '').trim(),
    branchPolicy: normalizeObject(input.branchPolicy || input.branch_policy),
    acceptanceTests: normalizeStringList(input.acceptanceTests || input.acceptance_tests),
    commitPolicy: normalizeObject(input.commitPolicy || input.commit_policy),
    reportingContract: normalizeObject(input.reportingContract || input.reporting_contract),
    escalationPolicy: {
      maxAutoRecoveryAttempts: numberOrDefault(input.escalationPolicy?.maxAutoRecoveryAttempts ?? input.escalation_policy?.maxAutoRecoveryAttempts, 1),
      ...normalizeObject(input.escalationPolicy || input.escalation_policy),
    },
    metadata: normalizeObject(input.metadata),
  };
}

function validateTaskPacket(packet = {}) {
  const normalized = createTaskPacket(packet);
  const errors = [];
  if (!normalized.objective) errors.push('objective is required');
  if (!Object.values(ScopeKind).includes(normalized.scope.kind)) errors.push(`invalid scope kind: ${normalized.scope.kind}`);
  if (normalized.scope.kind !== ScopeKind.WORKSPACE && !normalized.scope.path) {
    errors.push('scope.path is required when scope.kind is not workspace');
  }
  if (normalized.acceptanceTests.some((test) => !test.trim())) errors.push('acceptanceTests cannot contain empty commands');
  if (normalized.escalationPolicy.maxAutoRecoveryAttempts < 0) {
    errors.push('maxAutoRecoveryAttempts must be >= 0');
  }
  return {
    ok: errors.length === 0,
    errors,
    packet: normalized,
  };
}

function taskPacketFromToolArgs(args = {}, ctx = {}) {
  const packetInput = args.packet && typeof args.packet === 'object' ? args.packet : {};
  return createTaskPacket({
    objective: args.prompt || packetInput.objective || packetInput.prompt,
    repo: packetInput.repo || args.repo || ctx.repo || '',
    worktree: packetInput.worktree || args.worktree || ctx.cwd || '',
    scope: packetInput.scope || args.scope || ScopeKind.WORKSPACE,
    scopePath: packetInput.scopePath || args.scope_path || args.scopePath || '',
    branchPolicy: packetInput.branchPolicy || args.branch_policy,
    acceptanceTests: packetInput.acceptanceTests || args.acceptance_tests,
    commitPolicy: packetInput.commitPolicy || args.commit_policy,
    reportingContract: packetInput.reportingContract || args.reporting_contract,
    escalationPolicy: packetInput.escalationPolicy || args.escalation_policy,
    metadata: {
      ...(packetInput.metadata || {}),
      parentSessionId: ctx.sessionId || '',
      agent: args.agent || '',
    },
  });
}

function normalizeScopeKind(value) {
  const text = String(value || '').toLowerCase().replace(/-/g, '_');
  return Object.values(ScopeKind).includes(text) ? text : ScopeKind.CUSTOM;
}

function normalizeStringList(value) {
  if (!value) return [];
  return (Array.isArray(value) ? value : [value]).map((item) => String(item || ''));
}

function normalizeObject(value) {
  return value && typeof value === 'object' && !Array.isArray(value) ? { ...value } : {};
}

function numberOrDefault(value, fallback) {
  const n = Number(value);
  return Number.isFinite(n) ? n : fallback;
}

module.exports = {
  ScopeKind,
  createTaskPacket,
  taskPacketFromToolArgs,
  validateTaskPacket,
};
