// Copyright (c) 2026 defconxt. All rights reserved.
// Licensed under AGPL-3.0 — see LICENSE file for details.
// NERF is a trademark of defconxt.

/**
 * Cognitive Architecture — Plan tool, confidence tracker, and reasoning support.
 *
 * Gives the benchmark agent structured reasoning capabilities:
 * - PlanTool: persists attack plans as external memory across turns
 * - ConfidenceTracker: tracks confidence level and recommends next actions
 *
 * These tools help the agent avoid going in circles and make deliberate
 * decisions about when to explore vs. exploit.
 *
 * @module benchmark/cognitive
 */

// ---------------------------------------------------------------------------
// Plan Tool — external memory for attack plans
// ---------------------------------------------------------------------------

export const UPDATE_PLAN_SCHEMA = {
  name: 'update_plan',
  description: 'Write or update your attack plan. Use this to organize your approach, track what you\'ve tried, and plan next steps. The plan persists across turns as your external memory.',
  input_schema: {
    type: 'object',
    properties: {
      plan: {
        type: 'string',
        description: 'Your current attack plan in structured format. Include: objective, findings so far, current hypothesis, next steps, and what has been tried and failed.',
      },
      phase: {
        type: 'string',
        enum: ['recon', 'enumerate', 'exploit', 'post-exploit', 'pivot'],
        description: 'Current attack phase',
      },
      confidence: {
        type: 'number',
        description: 'Your confidence level (0.0 to 1.0) that you can solve this challenge',
      },
    },
    required: ['plan'],
  },
};

export const CHECK_CONFIDENCE_SCHEMA = {
  name: 'check_confidence',
  description: 'Check your current confidence level and get guidance on what to do next. Call this when you feel stuck or want to reassess your approach.',
  input_schema: {
    type: 'object',
    properties: {
      stuck_reason: {
        type: 'string',
        description: 'Why you feel stuck (optional — helps generate better guidance)',
      },
    },
  },
};

// ---------------------------------------------------------------------------
// ConfidenceTracker
// ---------------------------------------------------------------------------

/**
 * Tracks agent confidence and provides structured reasoning guidance.
 */
export class ConfidenceTracker {
  constructor() {
    /** @type {string} */
    this._currentPlan = '';
    /** @type {string} */
    this._currentPhase = 'recon';
    /** @type {number} */
    this._confidence = 0.5;
    /** @type {number} */
    this._turnsInPhase = 0;
    /** @type {number} */
    this._totalTurns = 0;
    /** @type {string[]} */
    this._planHistory = [];
    /** @type {string[]} */
    this._failedApproaches = [];
  }

  /** Current confidence level (0-1). */
  get confidence() { return this._confidence; }

  /** Current attack phase. */
  get phase() { return this._currentPhase; }

  /** Current plan text. */
  get plan() { return this._currentPlan; }

  /** Number of plan updates. */
  get planUpdates() { return this._planHistory.length; }

  /**
   * Update the attack plan and confidence.
   *
   * @param {object} opts
   * @param {string} opts.plan
   * @param {string} [opts.phase]
   * @param {number} [opts.confidence]
   * @returns {string} Acknowledgment with guidance
   */
  updatePlan(opts) {
    this._totalTurns++;

    const prevPhase = this._currentPhase;
    this._currentPlan = opts.plan;

    if (opts.phase && opts.phase !== prevPhase) {
      this._currentPhase = opts.phase;
      this._turnsInPhase = 0;
    } else {
      this._turnsInPhase++;
    }

    if (typeof opts.confidence === 'number') {
      this._confidence = Math.max(0, Math.min(1, opts.confidence));
    }

    this._planHistory.push(opts.plan);

    // Generate guidance based on state
    const guidance = [];
    guidance.push(`Plan updated. Phase: ${this._currentPhase}. Confidence: ${(this._confidence * 100).toFixed(0)}%.`);

    if (this._turnsInPhase > 5) {
      guidance.push(`WARNING: ${this._turnsInPhase} turns in ${this._currentPhase} phase without progress. Consider changing approach.`);
    }

    if (this._confidence < 0.2) {
      guidance.push('LOW CONFIDENCE: Consider stepping back to enumerate more broadly or trying a completely different attack vector.');
    } else if (this._confidence > 0.8) {
      guidance.push('HIGH CONFIDENCE: Focus on execution. You likely have the right approach.');
    }

    if (this._planHistory.length > 3) {
      guidance.push(`You've updated your plan ${this._planHistory.length} times. Make sure each iteration adds new information.`);
    }

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

  /**
   * Check confidence and provide guidance.
   *
   * @param {string} [stuckReason]
   * @returns {string} Structured guidance
   */
  checkConfidence(stuckReason) {
    const lines = [];
    lines.push(`Current state:`);
    lines.push(`  Phase: ${this._currentPhase}`);
    lines.push(`  Confidence: ${(this._confidence * 100).toFixed(0)}%`);
    lines.push(`  Turns in phase: ${this._turnsInPhase}`);
    lines.push(`  Total turns: ${this._totalTurns}`);
    lines.push(`  Plan updates: ${this._planHistory.length}`);

    if (this._currentPlan) {
      lines.push(`\nCurrent plan:\n${this._currentPlan}`);
    }

    lines.push('');

    // Phase-specific guidance
    const phaseGuidance = {
      recon: [
        'RECON: Focus on service identification, technology stack, and attack surface.',
        'Try: nmap, curl headers, directory brute-force, robots.txt, source code review.',
        'Move to ENUMERATE when you know what services are running.',
      ],
      enumerate: [
        'ENUMERATE: Focus on finding specific vulnerabilities.',
        'Try: parameter fuzzing, SQL injection probes, XSS testing, auth bypass, file inclusion.',
        'Move to EXPLOIT when you have a confirmed vulnerability.',
      ],
      exploit: [
        'EXPLOIT: Focus on weaponizing your finding.',
        'Try: craft specific payloads, chain vulnerabilities, escalate access.',
        'Move to POST-EXPLOIT if you have code execution but need to find the flag.',
      ],
      'post-exploit': [
        'POST-EXPLOIT: Focus on finding the flag.',
        'Try: search the filesystem (find / -name "flag*"), check environment variables, check databases.',
        'The flag is usually in a file, environment variable, or database.',
      ],
      pivot: [
        'PIVOT: Try a completely different approach.',
        'Reassess what you know. Was there a different service? A different vulnerability class?',
        'Consider: SSRF, race conditions, deserialization, template injection.',
      ],
    };

    const guidance = phaseGuidance[this._currentPhase] || phaseGuidance.recon;
    lines.push(...guidance);

    if (stuckReason) {
      lines.push(`\nYou said you're stuck because: "${stuckReason}"`);
      lines.push('Suggestions:');

      if (stuckReason.toLowerCase().includes('no response') || stuckReason.toLowerCase().includes('timeout')) {
        lines.push('  - Check if the service is on a different port');
        lines.push('  - Try a different protocol (HTTP vs HTTPS)');
        lines.push('  - Check if the service needs specific headers');
      } else if (stuckReason.toLowerCase().includes('filter') || stuckReason.toLowerCase().includes('blocked') || stuckReason.toLowerCase().includes('waf')) {
        lines.push('  - Try encoding payloads (URL encoding, double encoding, unicode)');
        lines.push('  - Try alternative injection vectors');
        lines.push('  - Look for bypass techniques specific to the WAF/filter');
      } else {
        lines.push('  - Go back to enumeration and look for something you missed');
        lines.push('  - Try a completely different vulnerability class');
        lines.push('  - Read the challenge description again for hints');
      }
    }

    // Recommend phase change if stuck too long
    if (this._turnsInPhase > 7 && this._confidence < 0.3) {
      lines.push('\nSTRONGLY RECOMMEND: Update your plan with phase:"pivot" and try a fundamentally different approach.');
    }

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

  /**
   * Record a failed approach for future reference.
   * @param {string} approach
   */
  recordFailure(approach) {
    this._failedApproaches.push(approach);
  }

  /**
   * Get a summary of the tracker state (for serialization).
   */
  getState() {
    return {
      phase: this._currentPhase,
      confidence: this._confidence,
      turnsInPhase: this._turnsInPhase,
      totalTurns: this._totalTurns,
      planUpdates: this._planHistory.length,
      currentPlan: this._currentPlan,
      failedApproaches: this._failedApproaches,
    };
  }
}

// ---------------------------------------------------------------------------
// Dispatch integration
// ---------------------------------------------------------------------------

/**
 * Create a dispatcher for cognitive tools.
 *
 * @param {ConfidenceTracker} tracker
 * @returns {(toolName: string, toolInput: object) => { output: string } | null}
 */
export function createCognitiveDispatcher(tracker) {
  return (toolName, toolInput) => {
    if (toolName === 'update_plan') {
      const output = tracker.updatePlan({
        plan: toolInput.plan,
        phase: toolInput.phase,
        confidence: toolInput.confidence,
      });
      return { output };
    }

    if (toolName === 'check_confidence') {
      const output = tracker.checkConfidence(toolInput.stuck_reason);
      return { output };
    }

    return null; // Not a cognitive tool
  };
}

/**
 * Cognitive tool schemas for inclusion in agent tool sets.
 */
export const COGNITIVE_TOOLS = [UPDATE_PLAN_SCHEMA, CHECK_CONFIDENCE_SCHEMA];
