// Tests for calibrated self-knowledge system

const path = require('path');
const os = require('os');
const fs = require('fs');

const mockPreDir = path.join(os.tmpdir(), `pre-test-cal-${process.pid}`);

jest.mock('../src/constants', () => ({
  PRE_DIR: mockPreDir,
  MODEL: 'pre-gemma4',
  MODEL_CTX: 8192,
  OLLAMA_PORT: 11434,
  MAX_TOOL_TURNS: 35,
  SESSIONS_DIR: require('path').join(mockPreDir, 'sessions'),
  MEMORY_DIR: require('path').join(mockPreDir, 'memory'),
  ARTIFACTS_DIR: require('path').join(mockPreDir, 'artifacts'),
  CONNECTIONS_FILE: require('path').join(mockPreDir, 'connections.json'),
  COMFYUI_FILE: require('path').join(mockPreDir, 'comfyui.json'),
  CRON_FILE: require('path').join(mockPreDir, 'cron.json'),
}));

const CALIBRATION_FILE = path.join(mockPreDir, 'calibration.json');

beforeAll(() => {
  fs.mkdirSync(mockPreDir, { recursive: true });
});

afterAll(() => {
  fs.rmSync(mockPreDir, { recursive: true, force: true });
});

beforeEach(() => {
  try { fs.unlinkSync(CALIBRATION_FILE); } catch (_e) {}
});


describe('Calibration — Tool Categorization', () => {
  test('categorizes known tools', () => {
    const cal = require('../src/calibration');
    expect(cal.categorize('bash')).toContain('bash');
    expect(cal.categorize('read_file')).toContain('file_ops');
    expect(cal.categorize('web_search')).toContain('web');
    expect(cal.categorize('apple_calendar')).toContain('calendar');
    expect(cal.categorize('github')).toContain('cloud');
  });

  test('unknown tools get categorized as general', () => {
    const cal = require('../src/calibration');
    expect(cal.categorize('unknown_tool_xyz')).toEqual(['general']);
  });
});


describe('Calibration — Recording Outcomes', () => {
  test('recordToolOutcome increments counters', () => {
    const cal = require('../src/calibration');

    cal.recordToolOutcome('bash', true);
    cal.recordToolOutcome('bash', true);
    cal.recordToolOutcome('bash', false);

    const profile = cal.loadProfile();
    expect(profile.categories.bash.successes).toBe(2);
    expect(profile.categories.bash.failures).toBe(1);
    expect(profile.categories.bash.total).toBe(3);
  });

  test('recordCorrection tracks correction count', () => {
    const cal = require('../src/calibration');

    cal.recordToolOutcome('bash', true);
    cal.recordCorrection(['bash']);

    const profile = cal.loadProfile();
    expect(profile.categories.bash.corrections).toBe(1);
  });

  test('overall counters aggregate across categories', () => {
    const cal = require('../src/calibration');

    cal.recordToolOutcome('bash', true);
    cal.recordToolOutcome('read_file', true);
    cal.recordToolOutcome('web_search', false);

    const profile = cal.loadProfile();
    expect(profile.overall.successes).toBe(2);
    expect(profile.overall.failures).toBe(1);
    expect(profile.overall.total).toBe(3);
  });
});


describe('Calibration — Confidence Scoring', () => {
  test('returns null for insufficient data', () => {
    const cal = require('../src/calibration');
    expect(cal.confidence({ successes: 2, failures: 0, corrections: 0, total: 2 })).toBeNull();
  });

  test('calculates high confidence for all successes', () => {
    const cal = require('../src/calibration');
    const score = cal.confidence({ successes: 10, failures: 0, corrections: 0, total: 10 });
    expect(score).toBe(1.0);
  });

  test('corrections penalize confidence', () => {
    const cal = require('../src/calibration');
    const noCorrections = cal.confidence({ successes: 8, failures: 2, corrections: 0, total: 10 });
    const withCorrections = cal.confidence({ successes: 8, failures: 2, corrections: 3, total: 10 });
    expect(withCorrections).toBeLessThan(noCorrections);
  });

  test('low success rate yields low confidence', () => {
    const cal = require('../src/calibration');
    const score = cal.confidence({ successes: 2, failures: 8, corrections: 0, total: 10 });
    expect(score).toBeLessThan(0.3);
  });
});


describe('Calibration — Feedback Detection', () => {
  test('detects positive feedback', () => {
    const cal = require('../src/calibration');
    expect(cal.detectFeedback('Perfect, thanks!', ['bash'])).toBe('positive');
    expect(cal.detectFeedback('Yes exactly', ['bash'])).toBe('positive');
    expect(cal.detectFeedback('Great job', ['bash'])).toBe('positive');
  });

  test('detects negative feedback', () => {
    const cal = require('../src/calibration');
    expect(cal.detectFeedback("No, that's wrong", ['bash'])).toBe('negative');
    expect(cal.detectFeedback('Try again', ['bash'])).toBe('negative');
    expect(cal.detectFeedback("That's not what I wanted", ['bash'])).toBe('negative');
  });

  test('returns null for neutral messages', () => {
    const cal = require('../src/calibration');
    expect(cal.detectFeedback('Now read the other file', ['bash'])).toBeNull();
    expect(cal.detectFeedback('What about the config?', ['bash'])).toBeNull();
  });

  test('negative feedback records a correction', () => {
    const cal = require('../src/calibration');
    cal.detectFeedback("No that's wrong", ['bash']);
    const profile = cal.loadProfile();
    expect(profile.categories.bash.corrections).toBeGreaterThanOrEqual(1);
  });
});


describe('Calibration — System Prompt Context', () => {
  test('returns empty string with no data', () => {
    const cal = require('../src/calibration');
    expect(cal.buildCalibrationContext()).toBe('');
  });

  test('includes strengths for high confidence categories', () => {
    const cal = require('../src/calibration');
    // Seed with good bash performance
    for (let i = 0; i < 10; i++) {
      cal.recordToolOutcome('bash', true);
    }

    const ctx = cal.buildCalibrationContext();
    expect(ctx).toContain('SELF-KNOWLEDGE');
    expect(ctx).toContain('Shell commands');
  });

  test('includes warnings for low confidence categories', () => {
    const cal = require('../src/calibration');
    // Seed with poor calendar performance
    for (let i = 0; i < 3; i++) {
      cal.recordToolOutcome('apple_calendar', true);
    }
    for (let i = 0; i < 5; i++) {
      cal.recordToolOutcome('apple_calendar', false);
    }
    cal.recordCorrection(['apple_calendar']);
    cal.recordCorrection(['apple_calendar']);

    const ctx = cal.buildCalibrationContext();
    expect(ctx).toContain('Caution area');
    expect(ctx).toContain('Calendar');
  });
});


describe('Calibration — Confidence Report', () => {
  test('returns structured report', () => {
    const cal = require('../src/calibration');
    for (let i = 0; i < 6; i++) cal.recordToolOutcome('bash', true);

    const report = cal.getConfidenceReport();
    expect(report).toHaveProperty('categories');
    expect(report).toHaveProperty('overall');
    expect(report).toHaveProperty('lastUpdated');
    expect(report.categories.bash).toBeTruthy();
    expect(report.categories.bash.confidence).toBeGreaterThan(0);
  });
});


describe('Calibration — Advisory', () => {
  test('returns null for high-confidence tools', () => {
    const cal = require('../src/calibration');
    for (let i = 0; i < 10; i++) cal.recordToolOutcome('bash', true);

    expect(cal.getAdvisory(['bash'])).toBeNull();
  });

  test('warns for low-confidence tools', () => {
    const cal = require('../src/calibration');
    for (let i = 0; i < 2; i++) cal.recordToolOutcome('apple_calendar', true);
    for (let i = 0; i < 5; i++) cal.recordToolOutcome('apple_calendar', false);
    cal.recordCorrection(['apple_calendar']);

    const advisory = cal.getAdvisory(['apple_calendar']);
    expect(advisory).not.toBeNull();
    expect(advisory).toContain('lower confidence');
  });
});
