'use strict';

const DEFAULT_RECIPIENT = 'agent';

function estimateTokens(content) {
  const text = String(content || '');
  if (!text) return 0;
  return Math.ceil(text.length / 4);
}

function createPromptSection({
  id,
  source = 'runtime',
  content = '',
  recipient = DEFAULT_RECIPIENT,
  cacheable = true,
  visibility = 'llm',
  mutableByHooks = true,
  tokenEstimate = null,
  redactionPolicy = 'none',
  metadata = {},
} = {}) {
  if (!id) throw new Error('Prompt section id is required');
  const text = String(content || '');
  return {
    id,
    source,
    content: text,
    recipient,
    cacheable: Boolean(cacheable),
    visibility,
    mutableByHooks: Boolean(mutableByHooks),
    tokenEstimate: tokenEstimate != null && Number.isFinite(Number(tokenEstimate))
      ? Number(tokenEstimate)
      : estimateTokens(text),
    redactionPolicy,
    metadata: { ...metadata },
  };
}

function redactPromptContent(content, policy = 'none') {
  const text = String(content || '');
  if (policy === 'none') return text;
  let redacted = text;
  if (policy === 'secrets' || policy === 'standard') {
    redacted = redacted
      .replace(/\b(sk-[A-Za-z0-9_-]{8,})\b/g, '[REDACTED_API_KEY]')
      .replace(/\b(AKIA[0-9A-Z]{16})\b/g, '[REDACTED_AWS_KEY]')
      .replace(/(token|secret|password)\s*[:=]\s*["'][^"']+["']/gi, '$1="[REDACTED]"');
  }
  if (policy === 'standard') {
    redacted = redacted.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, '[REDACTED_EMAIL]');
  }
  return redacted;
}

function normalizePromptSection(section) {
  if (!section) return null;
  if (typeof section === 'string') {
    return createPromptSection({ id: `inline-${hashString(section)}`, content: section });
  }
  return createPromptSection(section);
}

function buildPromptEnvelope({
  recipient = DEFAULT_RECIPIENT,
  stablePolicy = '',
  workspacePersona = '',
  projectContext = '',
  toolPolicy = '',
  providerContribution = '',
  channelContext = '',
  parentRunContext = '',
  childScope = '',
  runtimeOnlyContext = '',
  nextTurnContext = '',
  userTask = '',
  sections = [],
  metadata = {},
} = {}) {
  const built = [];
  addSection(built, {
    id: 'stable-policy',
    source: 'prompt-runtime',
    content: stablePolicy,
    recipient,
    cacheable: true,
    mutableByHooks: false,
  });
  addSection(built, {
    id: 'workspace-persona',
    source: 'workspace',
    content: workspacePersona,
    recipient,
    cacheable: true,
    redactionPolicy: 'standard',
  });
  addSection(built, {
    id: 'project-context',
    source: 'project',
    content: projectContext,
    recipient,
    cacheable: true,
  });
  addSection(built, {
    id: 'tool-policy',
    source: 'tools',
    content: toolPolicy,
    recipient,
    cacheable: true,
  });
  addSection(built, {
    id: 'provider-contribution',
    source: 'provider',
    content: providerContribution,
    recipient,
    cacheable: true,
  });
  addSection(built, {
    id: 'channel-context',
    source: 'channel',
    content: channelContext,
    recipient,
    cacheable: false,
    redactionPolicy: 'standard',
  });
  addSection(built, {
    id: 'parent-run-context',
    source: 'runtime',
    content: parentRunContext,
    recipient,
    cacheable: false,
  });
  addSection(built, {
    id: 'child-scope',
    source: 'runtime',
    content: childScope,
    recipient,
    cacheable: false,
  });
  addSection(built, {
    id: 'runtime-only-context',
    source: 'runtime',
    content: runtimeOnlyContext,
    recipient,
    cacheable: false,
    visibility: 'runtime-only',
  });
  addSection(built, {
    id: 'next-turn-context',
    source: 'runtime',
    content: nextTurnContext,
    recipient,
    cacheable: false,
  });
  addSection(built, {
    id: 'user-task',
    source: 'user',
    content: userTask,
    recipient,
    cacheable: false,
    mutableByHooks: false,
    redactionPolicy: 'standard',
  });
  for (const section of sections || []) {
    const normalized = normalizePromptSection(section);
    if (normalized && normalized.content) built.push(normalized);
  }
  return {
    version: 1,
    recipient,
    sections: built,
    metadata: { ...metadata },
    tokenEstimate: built.reduce((sum, section) => sum + section.tokenEstimate, 0),
  };
}

function addSection(target, section) {
  const normalized = normalizePromptSection(section);
  if (normalized && normalized.content) target.push(normalized);
}

function renderPromptEnvelope(envelope, { includeMetadata = false, includeRuntimeOnly = true } = {}) {
  const sections = (envelope?.sections || [])
    .filter(section => includeRuntimeOnly || section.visibility !== 'runtime-only')
    .map((section) => {
      const content = redactPromptContent(section.content, section.redactionPolicy);
      if (!includeMetadata) return content;
      const cache = section.cacheable ? 'cacheable' : 'dynamic';
      return `<!-- prompt-section:${section.id} source:${section.source} ${cache} -->\n${content}`;
    })
    .filter(Boolean);
  return sections.join('\n\n');
}

function buildChildScopeSection({ writeScope = [], mode = 'build', parentRunId = '', instructions = '' } = {}) {
  const scopes = Array.isArray(writeScope) ? writeScope : (writeScope ? [writeScope] : []);
  return createPromptSection({
    id: 'child-scope',
    source: 'agent-runtime',
    cacheable: false,
    content: [
      `Child mode: ${mode}`,
      parentRunId ? `Parent run: ${parentRunId}` : '',
      scopes.length ? `Write scope: ${scopes.join(', ')}` : '',
      instructions,
    ].filter(Boolean).join('\n'),
  });
}

function buildReviewerEnvelope({ diff = '', tests = '', context = '', builder = '', instructions = '' } = {}) {
  return buildPromptEnvelope({
    recipient: 'reviewer',
    stablePolicy: 'You are reviewing coding work. Identify correctness, safety, and maintainability issues. Prefer actionable findings over style comments.',
    parentRunContext: builder ? `Builder: ${builder}` : '',
    runtimeOnlyContext: context,
    userTask: [
      instructions,
      diff ? `Diff:\n${diff}` : '',
      tests ? `Tests:\n${tests}` : '',
    ].filter(Boolean).join('\n\n'),
  });
}

function hashString(text) {
  let hash = 0;
  const input = String(text || '');
  for (let i = 0; i < input.length; i += 1) {
    hash = ((hash << 5) - hash + input.charCodeAt(i)) | 0;
  }
  return Math.abs(hash).toString(36);
}

module.exports = {
  buildChildScopeSection,
  buildPromptEnvelope,
  buildReviewerEnvelope,
  createPromptSection,
  estimateTokens,
  normalizePromptSection,
  redactPromptContent,
  renderPromptEnvelope,
};
