'use strict';

/**
 * Unit tests for tool-labels.js
 */

const { describe, it, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');
const path = require('path');
const fs = require('fs');
const os = require('os');

const { loadLabels, resolve, resetLabels } = require('../../src/tool-labels');

describe('tool-labels.js', () => {
  beforeEach(() => {
    resetLabels();
  });

  afterEach(() => {
    resetLabels();
  });

  describe('exact match', () => {
    it('resolves known tools by exact name', () => {
      loadLabels(null);
      assert.equal(resolve('exec'), 'Running command...');
      assert.equal(resolve('Read'), 'Reading file...');
      assert.equal(resolve('Write'), 'Writing file...');
      assert.equal(resolve('Edit'), 'Editing file...');
      assert.equal(resolve('web_search'), 'Searching the web...');
      assert.equal(resolve('web_fetch'), 'Fetching URL...');
      assert.equal(resolve('message'), 'Sending message...');
      assert.equal(resolve('tts'), 'Generating speech...');
      assert.equal(resolve('subagents'), 'Managing sub-agents...');
      assert.equal(resolve('image'), 'Analyzing image...');
      assert.equal(resolve('process'), 'Managing process...');
      assert.equal(resolve('browser'), 'Controlling browser...');
    });
  });

  describe('prefix match', () => {
    it('resolves camofox_ tools via prefix', () => {
      loadLabels(null);
      assert.equal(resolve('camofox_create_tab'), 'Opening browser tab...'); // exact takes priority
      assert.equal(resolve('camofox_some_new_tool'), 'Using browser...');
    });

    it('resolves claude_code_ tools via prefix', () => {
      loadLabels(null);
      assert.equal(resolve('claude_code_start'), 'Starting Claude Code task...'); // exact takes priority
      assert.equal(resolve('claude_code_something_new'), 'Running Claude Code...');
    });
  });

  describe('default label', () => {
    it('returns default for unknown tools', () => {
      loadLabels(null);
      assert.equal(resolve('some_unknown_tool'), 'Working...');
      assert.equal(resolve(''), 'Working...');
      assert.equal(resolve('xyz'), 'Working...');
    });
  });

  describe('external override', () => {
    let tmpFile;

    beforeEach(() => {
      tmpFile = path.join(os.tmpdir(), `tool-labels-test-${Date.now()}.json`);
    });

    afterEach(() => {
      try {
        fs.unlinkSync(tmpFile);
      } catch (_e) {
        /* ignore */
      }
    });

    it('external exact overrides built-in', () => {
      fs.writeFileSync(
        tmpFile,
        JSON.stringify({
          exact: { exec: 'Custom exec label...' },
          prefix: {},
        }),
      );
      loadLabels(tmpFile);
      assert.equal(resolve('exec'), 'Custom exec label...');
      // Non-overridden built-in still works
      assert.equal(resolve('Read'), 'Reading file...');
    });

    it('external prefix adds new prefix', () => {
      fs.writeFileSync(
        tmpFile,
        JSON.stringify({
          exact: {},
          prefix: { my_tool_: 'My custom tool...' },
        }),
      );
      loadLabels(tmpFile);
      assert.equal(resolve('my_tool_do_something'), 'My custom tool...');
    });

    it('external default overrides built-in default', () => {
      fs.writeFileSync(
        tmpFile,
        JSON.stringify({
          exact: {},
          prefix: {},
          default: 'Custom default...',
        }),
      );
      loadLabels(tmpFile);
      assert.equal(resolve('completely_unknown'), 'Custom default...');
    });

    it('handles missing external file gracefully', () => {
      loadLabels('/nonexistent/path/tool-labels.json');
      // Should fall back to built-in
      assert.equal(resolve('exec'), 'Running command...');
    });

    it('handles malformed external JSON gracefully', () => {
      fs.writeFileSync(tmpFile, 'not valid json {{{');
      loadLabels(tmpFile);
      // Should fall back to built-in
      assert.equal(resolve('exec'), 'Running command...');
    });
  });

  describe('regex match', () => {
    let tmpFile;

    beforeEach(() => {
      tmpFile = path.join(os.tmpdir(), `tool-labels-regex-${Date.now()}.json`);
    });

    afterEach(() => {
      try {
        fs.unlinkSync(tmpFile);
      } catch (_e) {
        /* ignore */
      }
    });

    it('resolves via regex pattern', () => {
      fs.writeFileSync(
        tmpFile,
        JSON.stringify({
          exact: {},
          prefix: {},
          regex: [{ pattern: '/^my_api_/', label: 'Calling API...' }],
        }),
      );
      loadLabels(tmpFile);
      assert.equal(resolve('my_api_create'), 'Calling API...');
      assert.equal(resolve('my_api_update'), 'Calling API...');
      assert.equal(resolve('other_tool'), 'Working...');
    });

    it('handles invalid regex gracefully', () => {
      fs.writeFileSync(
        tmpFile,
        JSON.stringify({
          exact: {},
          prefix: {},
          regex: [{ pattern: '/[invalid(/', label: 'oops' }],
        }),
      );
      loadLabels(tmpFile);
      // Invalid regex skipped — returns default
      assert.equal(resolve('anything'), 'Working...');
    });
  });

  describe('auto-load', () => {
    it('auto-loads built-in labels on first resolve call', () => {
      // resetLabels was called in beforeEach — no explicit loadLabels call
      const label = resolve('exec');
      assert.equal(label, 'Running command...');
    });
  });
});
