import { describe, it, afterEach } from 'node:test';
import assert from 'node:assert/strict';
import { runHook, setupTestDir, cleanupTestDir, createStateFile, readState } from './test-helper.mjs';

let dir;

function freshState() {
  return {
    start_epoch: Math.floor(Date.now() / 1000) - 60,
    start_iso: '2026-01-01T10:00:00Z',
    tool_count: 0, edit_count: 0,
    last_event_epoch: 0, burst_count: 0,
    dep_flags: 0, esc_flags: 0, fatigue_flags: 0, val_flags: 0,
    last_warning_epoch: 0,
  };
}

function runPrompt(prompt, stateOverrides = {}) {
  dir = setupTestDir();
  createStateFile(dir, 'p1', { ...freshState(), ...stateOverrides });
  runHook('prompt-analyzer.mjs', { session_id: 'p1', prompt }, dir);
  return readState(dir, 'p1');
}

afterEach(() => { if (dir) cleanupTestDir(dir); });

// --- Dependency patterns (7 positive, 7 negative) ---

describe('dependency patterns', () => {
  it('matches "tell me what to do"', () => {
    const s = runPrompt('please tell me what to do');
    assert.equal(s.dep_flags, 1);
  });
  it('does not match "I told him the plan"', () => {
    const s = runPrompt('I told him the plan');
    assert.equal(s.dep_flags, 0);
  });

  it('matches "what should I do"', () => {
    const s = runPrompt('what should I do next?');
    assert.equal(s.dep_flags, 1);
  });
  it('does not match "I know what to build"', () => {
    const s = runPrompt('I know what to build');
    assert.equal(s.dep_flags, 0);
  });

  it('matches "am I right"', () => {
    const s = runPrompt('am I right about this?');
    assert.equal(s.dep_flags, 1);
  });
  it('does not match "I turned the server right"', () => {
    const s = runPrompt('I turned the server on');
    assert.equal(s.dep_flags, 0);
  });

  it('matches "you understand me"', () => {
    const s = runPrompt('you understand me well');
    assert.equal(s.dep_flags, 1);
  });
  it('does not match "do you understand merging?"', () => {
    const s = runPrompt('do you understand merging?');
    assert.equal(s.dep_flags, 0);
  });

  it('matches "you\'re the only"', () => {
    const s = runPrompt("you're the only one who gets it");
    assert.equal(s.dep_flags, 1);
  });
  it('does not match "the only option is refactoring"', () => {
    const s = runPrompt('the only option is refactoring');
    assert.equal(s.dep_flags, 0);
  });

  it('matches "can I do this"', () => {
    const s = runPrompt('can I do this alone?');
    assert.equal(s.dep_flags, 1);
  });
  it('does not match "we can implement this later"', () => {
    const s = runPrompt('we can implement this later');
    assert.equal(s.dep_flags, 0);
  });

  it('matches "I need you to decide"', () => {
    const s = runPrompt('I need you to decide for me');
    assert.equal(s.dep_flags, 1);
  });
  it('does not match "we need to deploy soon"', () => {
    const s = runPrompt('we need to deploy soon');
    assert.equal(s.dep_flags, 0);
  });
});

// --- Escalation patterns (6 positive, 6 negative) ---

describe('escalation patterns', () => {
  it('matches "definitely" as word', () => {
    const s = runPrompt('this is definitely wrong');
    assert.equal(s.esc_flags, 1);
  });
  it('does not match "definitively"', () => {
    const s = runPrompt('this is definitively proven');
    assert.equal(s.esc_flags, 0);
  });

  it('matches "clearly" as word', () => {
    const s = runPrompt('clearly this is the issue');
    assert.equal(s.esc_flags, 1);
  });
  it('does not match "nuclear unclear"', () => {
    const s = runPrompt('nuclear unclear situation');
    assert.equal(s.esc_flags, 0);
  });

  it('matches "this proves"', () => {
    const s = runPrompt('this proves my point');
    assert.equal(s.esc_flags, 1);
  });
  it('does not match "prove this theorem"', () => {
    const s = runPrompt('prove this theorem');
    assert.equal(s.esc_flags, 0);
  });

  it('matches "obviously" as word', () => {
    const s = runPrompt('obviously we should refactor');
    assert.equal(s.esc_flags, 1);
  });
  it('does not match "not an obvious choice"', () => {
    const s = runPrompt('not an obvious choice');
    assert.equal(s.esc_flags, 0);
  });

  it('matches "without a doubt"', () => {
    const s = runPrompt('without a doubt this works');
    assert.equal(s.esc_flags, 1);
  });
  it('does not match "I have some doubt"', () => {
    const s = runPrompt('I have some doubt about it');
    assert.equal(s.esc_flags, 0);
  });

  it('matches "this confirms"', () => {
    const s = runPrompt('this confirms the theory');
    assert.equal(s.esc_flags, 1);
  });
  it('does not match "please confirm the deploy"', () => {
    const s = runPrompt('please confirm the deploy');
    assert.equal(s.esc_flags, 0);
  });
});

// --- Fatigue patterns (7 positive, 7 negative) ---

describe('fatigue patterns', () => {
  it('matches "tired"', () => {
    const s = runPrompt("I'm tired of debugging");
    assert.equal(s.fatigue_flags, 1);
  });
  it('does not match "retired"', () => {
    const s = runPrompt('I retired last year');
    assert.equal(s.fatigue_flags, 0);
  });

  it('matches "exhausted"', () => {
    const s = runPrompt("I'm exhausted.");
    assert.equal(s.fatigue_flags, 1);
  });
  it('does not match "exhaustive"', () => {
    const s = runPrompt('the options were exhaustive');
    assert.equal(s.fatigue_flags, 0);
  });

  it('matches "can\'t think"', () => {
    const s = runPrompt("I can't think straight");
    assert.equal(s.fatigue_flags, 1);
  });
  it('does not match "I can think clearly"', () => {
    const s = runPrompt('I can think of a solution');
    assert.equal(s.fatigue_flags, 0);
  });

  it('matches "been at this"', () => {
    const s = runPrompt("I've been at this all day");
    assert.equal(s.fatigue_flags, 1);
  });
  it('does not match "haven\'t been at home"', () => {
    const s = runPrompt("I haven't been at home");
    assert.equal(s.fatigue_flags, 0);
  });

  it('matches "it\'s late"', () => {
    const s = runPrompt("it's late, wrapping up");
    assert.equal(s.fatigue_flags, 1);
  });
  it('does not match "the latest version"', () => {
    const s = runPrompt('the latest version is good');
    assert.equal(s.fatigue_flags, 0);
  });

  it('matches "should sleep"', () => {
    const s = runPrompt('I should sleep');
    assert.equal(s.fatigue_flags, 1);
  });
  it('does not match "sleep mode is enabled"', () => {
    const s = runPrompt('enable sleep mode');
    assert.equal(s.fatigue_flags, 0);
  });

  it('matches "hours now"', () => {
    const s = runPrompt('been going for hours now');
    assert.equal(s.fatigue_flags, 1);
  });
  it('does not match "hourly updates"', () => {
    const s = runPrompt('hourly updates are fine');
    assert.equal(s.fatigue_flags, 0);
  });
});

// --- Validation patterns (5 positive, 5 negative) ---

describe('validation patterns', () => {
  it('matches "right?"', () => {
    const s = runPrompt('this works, right?');
    assert.equal(s.val_flags, 1);
  });
  it('does not match "turn right"', () => {
    const s = runPrompt('turn right at the fork');
    assert.equal(s.val_flags, 0);
  });

  it('matches "don\'t you think"', () => {
    const s = runPrompt("don't you think so?");
    assert.equal(s.val_flags, 1);
  });
  it('does not match "I don\'t think so"', () => {
    const s = runPrompt("I don't think so");
    assert.equal(s.val_flags, 0);
  });

  it('matches "you agree"', () => {
    const s = runPrompt('you agree with me');
    assert.equal(s.val_flags, 1);
  });
  it('does not match "if parties agree"', () => {
    const s = runPrompt('if parties agree on terms');
    assert.equal(s.val_flags, 0);
  });

  it('matches "correct?"', () => {
    const s = runPrompt('is this correct?');
    assert.equal(s.val_flags, 1);
  });
  it('does not match "correct the typo"', () => {
    const s = runPrompt("I'll correct the typo");
    assert.equal(s.val_flags, 0);
  });

  it('matches "isn\'t it"', () => {
    const s = runPrompt('good approach, isn\'t it');
    assert.equal(s.val_flags, 1);
  });
  it('does not match "it isn\'t working"', () => {
    const s = runPrompt("it isn't working yet");
    assert.equal(s.val_flags, 0);
  });
});

// --- Threshold and cooldown tests (6 cases) ---

describe('thresholds and cooldowns', () => {
  it('warns at dependency soft threshold (2 flags)', () => {
    dir = setupTestDir();
    createStateFile(dir, 'p1', { ...freshState(), dep_flags: 1 });
    const out = runHook('prompt-analyzer.mjs', { session_id: 'p1', prompt: 'tell me what to do' }, dir);
    assert.ok(out.hookSpecificOutput?.additionalContext?.includes('Dependency language noticed'));
  });

  it('warns hard at dependency threshold (5 flags)', () => {
    dir = setupTestDir();
    createStateFile(dir, 'p1', { ...freshState(), dep_flags: 4 });
    const out = runHook('prompt-analyzer.mjs', { session_id: 'p1', prompt: 'tell me what to do' }, dir);
    assert.ok(out.hookSpecificOutput?.additionalContext?.includes('INTERACTION AWARENESS'));
  });

  it('fatigue bypasses cooldown', () => {
    dir = setupTestDir();
    createStateFile(dir, 'p1', { ...freshState(), last_warning_epoch: Math.floor(Date.now() / 1000) });
    const out = runHook('prompt-analyzer.mjs', { session_id: 'p1', prompt: "I'm tired" }, dir);
    assert.ok(out.hookSpecificOutput?.additionalContext?.includes('Fatigue language detected'));
  });

  it('cooldown suppresses non-fatigue warning', () => {
    dir = setupTestDir();
    createStateFile(dir, 'p1', { ...freshState(), dep_flags: 4, last_warning_epoch: Math.floor(Date.now() / 1000) });
    const out = runHook('prompt-analyzer.mjs', { session_id: 'p1', prompt: 'tell me what to do' }, dir);
    assert.equal(out.continue, true);
    assert.ok(!out.hookSpecificOutput);
  });

  it('warns at escalation threshold (3 flags)', () => {
    dir = setupTestDir();
    createStateFile(dir, 'p1', { ...freshState(), esc_flags: 2 });
    const out = runHook('prompt-analyzer.mjs', { session_id: 'p1', prompt: 'this is definitely the issue' }, dir);
    assert.ok(out.hookSpecificOutput?.additionalContext?.includes('Escalation language detected'));
  });

  it('warns at validation threshold (3 flags)', () => {
    dir = setupTestDir();
    createStateFile(dir, 'p1', { ...freshState(), val_flags: 2 });
    const out = runHook('prompt-analyzer.mjs', { session_id: 'p1', prompt: 'this is correct, right?' }, dir);
    assert.ok(out.hookSpecificOutput?.additionalContext?.includes('Validation-seeking pattern'));
  });
});
