const { requestModel } = require('./llmGateway');
const { toolDefinitions } = require('./toolRegistry');

const safeJsonParse = (value) => {
  try {
    return JSON.parse(value);
  } catch {
    return null;
  }
};

const buildFallbackPlan = ({ agent, input }) => ({
  goal: input?.objective || agent.description || agent.name,
  steps: (agent.tools || []).slice(0, agent.modelPolicy?.maxSteps || 8).map((tool, index) => ({
    id: `tool-${index + 1}`,
    tool,
    input: input?.toolInputs?.[tool] || input || {},
    requiresApproval: false,
    riskLevel: toolDefinitions.find((item) => item.key === tool)?.riskLevel || 'low',
  })),
  finalInstruction: agent.instructions,
});

const normalizePlan = ({ candidate, agent, actor }) => {
  const base = candidate && typeof candidate === 'object' ? candidate : {};
  const allowedTools = new Set(agent.tools || []);
  const steps = Array.isArray(base.steps) ? base.steps : [];
  return {
    goal: String(base.goal || agent.description || agent.name || 'Complete the requested work').slice(0, 400),
    steps: steps
      .filter((step) => step && allowedTools.has(step.tool))
      .slice(0, agent.modelPolicy?.maxSteps || 8)
      .map((step, index) => ({
        id: step.id || `step-${index + 1}`,
        tool: step.tool,
        input: step.input && typeof step.input === 'object' ? step.input : {},
        requiresApproval: Boolean(step.requiresApproval),
        riskLevel: step.riskLevel || toolDefinitions.find((item) => item.key === step.tool)?.riskLevel || 'low',
        actor: actor?._id,
      })),
    finalInstruction: String(base.finalInstruction || agent.instructions || '').slice(0, 2000),
  };
};

const buildHermesPrompt = ({ agent, input, history, knowledge }) =>
  JSON.stringify({
    objective: input?.objective || input?.goal || agent.description,
    input,
    priorSteps: history,
    knowledge,
    limits: agent.limits,
    allowedTools: (agent.tools || []).map((key) => {
      const definition = toolDefinitions.find((item) => item.key === key) || { key };
      return { key: definition.key, label: definition.label, permission: definition.permission, riskLevel: definition.riskLevel };
    }),
  });

const orchestrateWithHermes = async ({ agent, input, history = [], knowledge = [], actor, providers }) => {
  const result = await requestModel({
    policy: {
      provider: 'hermes',
      fallbackProviders: [agent.modelPolicy?.provider, ...(agent.modelPolicy?.fallbackProviders || ['openai', 'kimi'])].filter(Boolean),
      temperature: 0.1,
      model: agent.modelPolicy?.model,
    },
    action: 'orchestrate',
    instruction:
      'You are Hermes, the primary orchestration engine. Return JSON only with keys goal, steps, finalInstruction. Each step must use one allowed tool only.',
    prompt: buildHermesPrompt({ agent, input, history, knowledge }),
    providers,
  });

  const candidate = safeJsonParse(result.content) || result.decision || result.raw?.plan || result.raw;
  const plan = normalizePlan({ candidate, agent, actor });
  if (!plan.steps.length) {
    return { ...result, plan: buildFallbackPlan({ agent, input }) };
  }
  return { ...result, plan };
};

module.exports = {
  orchestrateWithHermes,
  normalizePlan,
  buildFallbackPlan,
};
