import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { parseFrontmatter, parseSimpleYaml, parseJson, findImports, extractSections } from '../../scanners/lib/yaml-parser.mjs';

describe('parseFrontmatter', () => {
  it('parses standard frontmatter', () => {
    const content = '---\nname: test\nmodel: opus\n---\n\nBody here';
    const { frontmatter, body } = parseFrontmatter(content);
    assert.deepStrictEqual(frontmatter, { name: 'test', model: 'opus' });
    assert.ok(body.includes('Body here'));
  });

  it('returns null frontmatter when none exists', () => {
    const { frontmatter, body } = parseFrontmatter('Just body text');
    assert.strictEqual(frontmatter, null);
    assert.strictEqual(body, 'Just body text');
  });

  it('handles empty frontmatter', () => {
    const { frontmatter } = parseFrontmatter('---\n---\nBody');
    assert.deepStrictEqual(frontmatter, {});
  });

  it('calculates bodyStartLine correctly', () => {
    const content = '---\na: 1\nb: 2\n---\nBody';
    const { bodyStartLine } = parseFrontmatter(content);
    assert.strictEqual(bodyStartLine, 5);
  });
});

describe('parseSimpleYaml', () => {
  it('parses key-value pairs', () => {
    const result = parseSimpleYaml('name: test\nmodel: opus');
    assert.strictEqual(result.name, 'test');
    assert.strictEqual(result.model, 'opus');
  });

  it('parses boolean values', () => {
    const result = parseSimpleYaml('enabled: true\ndisabled: false');
    assert.strictEqual(result.enabled, true);
    assert.strictEqual(result.disabled, false);
  });

  it('parses numeric values', () => {
    const result = parseSimpleYaml('count: 42\nrate: 3.14');
    assert.strictEqual(result.count, 42);
    assert.strictEqual(result.rate, 3.14);
  });

  it('parses inline arrays', () => {
    const result = parseSimpleYaml('tools: [Read, Write, Bash]');
    assert.deepStrictEqual(result.tools, ['Read', 'Write', 'Bash']);
  });

  it('strips quotes from values', () => {
    const result = parseSimpleYaml('name: "quoted value"');
    assert.strictEqual(result.name, 'quoted value');
  });

  it('normalizes hyphens to underscores in keys', () => {
    const result = parseSimpleYaml('allowed-tools: Read');
    assert.ok('allowed_tools' in result);
  });

  it('normalizes comma-separated strings in list fields', () => {
    const result = parseSimpleYaml('allowed-tools: Read, Write, Bash');
    assert.deepStrictEqual(result.allowed_tools, ['Read', 'Write', 'Bash']);
  });

  it('handles null values', () => {
    const result = parseSimpleYaml('value: null\ntilde: ~\nempty:');
    assert.strictEqual(result.value, null);
    assert.strictEqual(result.tilde, null);
    assert.strictEqual(result.empty, null);
  });

  it('skips comments', () => {
    const result = parseSimpleYaml('# comment\nname: test\n# another');
    assert.strictEqual(result.name, 'test');
    assert.strictEqual(Object.keys(result).length, 1);
  });

  it('handles multi-line pipe values', () => {
    const result = parseSimpleYaml('description: |\n  Line 1\n  Line 2\nname: test');
    assert.ok(result.description.includes('Line 1'));
    assert.ok(result.description.includes('Line 2'));
    assert.strictEqual(result.name, 'test');
  });
});

describe('parseJson', () => {
  it('parses valid JSON', () => {
    const result = parseJson('{"key": "value"}');
    assert.deepStrictEqual(result, { key: 'value' });
  });

  it('returns null for invalid JSON', () => {
    assert.strictEqual(parseJson('{invalid}'), null);
  });

  it('returns null for empty string', () => {
    assert.strictEqual(parseJson(''), null);
  });
});

describe('findImports', () => {
  it('finds @import lines', () => {
    const content = '# Title\n@path/to/file.md\nSome text\n@another/file.md';
    const imports = findImports(content);
    assert.strictEqual(imports.length, 2);
    assert.strictEqual(imports[0].path, 'path/to/file.md');
    assert.strictEqual(imports[0].line, 2);
    assert.strictEqual(imports[1].path, 'another/file.md');
    assert.strictEqual(imports[1].line, 4);
  });

  it('returns empty array when no imports', () => {
    assert.deepStrictEqual(findImports('Just text'), []);
  });

  it('ignores @ in the middle of lines', () => {
    const imports = findImports('Email me at user@example.com');
    assert.strictEqual(imports.length, 0);
  });
});

describe('extractSections', () => {
  it('extracts markdown headings', () => {
    const content = '# Title\n## Section 1\nText\n### Sub-section\n## Section 2';
    const sections = extractSections(content);
    assert.strictEqual(sections.length, 4);
    assert.strictEqual(sections[0].heading, 'Title');
    assert.strictEqual(sections[0].level, 1);
    assert.strictEqual(sections[1].heading, 'Section 1');
    assert.strictEqual(sections[1].level, 2);
  });

  it('returns empty for no headings', () => {
    assert.deepStrictEqual(extractSections('Just plain text'), []);
  });

  it('includes line numbers', () => {
    const content = 'line1\n## Heading\nline3';
    const sections = extractSections(content);
    assert.strictEqual(sections[0].line, 2);
  });
});
