/**
 * Gitagent Prompt Builder
 *
 * Converts a GitagentDefinition (from parser.js) into strings/configs
 * that can be injected into Claude SDK options.
 */

/**
 * Model name mapping from gitagent spec model IDs to UpfynAI model IDs.
 * Gitagent uses full Anthropic model IDs; we map to short names.
 */
const MODEL_MAP = {
  'claude-opus-4-6':            'opus',
  'claude-opus-4-20250514':     'opus',
  'claude-sonnet-4-6':          'sonnet',
  'claude-sonnet-4-5-20250929': 'sonnet',
  'claude-haiku-4-5-20251001':  'haiku',
  // Generic short names pass through
  'opus':   'opus',
  'sonnet': 'sonnet',
  'haiku':  'haiku',
};

/**
 * Build a system prompt appendix from a parsed gitagent definition.
 * Wrapped in <gitagent-context> tags so Claude can distinguish it.
 *
 * @param {import('./parser.js').GitagentDefinition} def
 * @returns {string}
 */
export function buildSystemPromptAppendix(def) {
  const sections = [];

  // Identity header from manifest
  const m = def.manifest;
  sections.push(`# Gitagent: ${m.name} v${m.version || '0.0.0'}`);
  if (m.description) sections.push(m.description);

  // SOUL — agent identity & personality
  if (def.soul) {
    sections.push(`## Identity (SOUL)\n${def.soul}`);
  }

  // RULES — hard constraints
  if (def.rules) {
    sections.push(`## Rules\n${def.rules}`);
  }

  // AGENTS — framework-agnostic instructions
  if (def.agents) {
    sections.push(`## Agent Instructions\n${def.agents}`);
  }

  // Skills
  if (def.skills && def.skills.length > 0) {
    const skillLines = def.skills.map(s => {
      const header = `### ${s.name}`;
      const meta = [];
      if (s.version) meta.push(`v${s.version}`);
      if (s.tools && s.tools.length) meta.push(`tools: ${s.tools.join(', ')}`);
      const metaLine = meta.length ? ` (${meta.join(' | ')})` : '';
      return `${header}${metaLine}\n${s.description || ''}`;
    });
    sections.push(`## Skills\n${skillLines.join('\n\n')}`);
  }

  // Tools
  if (def.tools && def.tools.length > 0) {
    const toolLines = def.tools.map(t => {
      const parts = [`### ${t.name}`];
      if (t.description) parts.push(t.description);
      if (t.input_schema || t.parameters) {
        const schema = t.input_schema || t.parameters;
        if (schema.properties) {
          const props = Object.entries(schema.properties)
            .map(([k, v]) => `- \`${k}\`: ${v.type || 'any'}${v.description ? ' — ' + v.description : ''}`)
            .join('\n');
          parts.push(`Parameters:\n${props}`);
        }
      }
      return parts.join('\n');
    });
    sections.push(`## Tools\n${toolLines.join('\n\n')}`);
  }

  // Knowledge (always-loaded docs)
  if (def.knowledge && def.knowledge.alwaysLoadDocs && def.knowledge.alwaysLoadDocs.length > 0) {
    const knowledgeLines = def.knowledge.alwaysLoadDocs.map(d =>
      `### ${d.title}\n${d.content}`
    );
    sections.push(`## Knowledge\n${knowledgeLines.join('\n\n')}`);
  }

  // Memory
  if (def.memory) {
    sections.push(`## Memory\n${def.memory}`);
  }

  // Runtime constraints
  if (m.runtime) {
    const rc = [];
    if (m.runtime.max_turns) rc.push(`Max turns: ${m.runtime.max_turns}`);
    if (m.runtime.timeout) rc.push(`Timeout: ${m.runtime.timeout}s`);
    if (rc.length) sections.push(`## Runtime\n${rc.join('\n')}`);
  }

  return sections.join('\n\n');
}

/**
 * Map a gitagent model config to an UpfynAI model ID.
 * @param {Object|string} modelConfig - model field from agent.yaml
 * @returns {string|null} UpfynAI model ID or null if no mapping
 */
export function mapGitagentModel(modelConfig) {
  if (!modelConfig) return null;

  // String shorthand: model: "claude-sonnet-4-5-20250929"
  if (typeof modelConfig === 'string') {
    return MODEL_MAP[modelConfig] || null;
  }

  // Object form: model: { preferred: "...", fallback: [...] }
  if (modelConfig.preferred) {
    return MODEL_MAP[modelConfig.preferred] || null;
  }

  return null;
}

/**
 * Extract a deduplicated list of allowed tool names from all parsed skills.
 * @param {Array} skills - Parsed skill definitions
 * @returns {string[]}
 */
export function extractAllowedTools(skills) {
  if (!skills || skills.length === 0) return [];

  const toolSet = new Set();
  for (const skill of skills) {
    if (skill.tools && Array.isArray(skill.tools)) {
      for (const t of skill.tools) {
        toolSet.add(t);
      }
    }
    if (skill.allowed_tools && Array.isArray(skill.allowed_tools)) {
      for (const t of skill.allowed_tools) {
        toolSet.add(t);
      }
    }
  }
  return Array.from(toolSet);
}
