import { describe, it, expect } from 'vitest';
import { parseNoteFm, serializeNoteFm, NoteFm } from './fm.js';

describe('parseNoteFm', () => {
  it('parses valid frontmatter with all fields', () => {
    const md = `---
title: CVE-2026-1234
visibility: org
scope_org_id: my-team
mode_hint: inject
tags: [cve, kubernetes]
---

body text`;
    const result = parseNoteFm(md);
    expect(result.fm).toEqual({
      title: 'CVE-2026-1234',
      visibility: 'org',
      scope_org_id: 'my-team',
      mode_hint: 'inject',
      tags: ['cve', 'kubernetes'],
    });
    expect(result.body.trim()).toBe('body text');
  });

  it('defaults to visibility=private when FM missing', () => {
    const md = `just a body`;
    const result = parseNoteFm(md);
    expect(result.fm.visibility).toBe('private');
    expect(result.body).toBe('just a body');
  });

  it('rejects invalid visibility value', () => {
    const md = `---
visibility: world
---
body`;
    expect(() => parseNoteFm(md)).toThrow(/visibility/);
  });

  it('rejects org visibility without scope_org_id', () => {
    const md = `---
visibility: org
---
body`;
    expect(() => parseNoteFm(md)).toThrow(/scope_org_id/);
  });

  it('rejects invalid mode_hint', () => {
    const md = `---
visibility: private
mode_hint: bogus
---
body`;
    expect(() => parseNoteFm(md)).toThrow(/mode_hint/);
  });

  it('drops scope_org_id when visibility is not org', () => {
    const md = `---
visibility: public
scope_org_id: my-team
---
body`;
    const result = parseNoteFm(md);
    expect(result.fm.scope_org_id).toBeNull();
  });

  it('normalizes tags to string array', () => {
    const md = `---
visibility: private
tags: [a, b, c]
---
body`;
    expect(parseNoteFm(md).fm.tags).toEqual(['a', 'b', 'c']);
  });
});

describe('serializeNoteFm', () => {
  it('round-trips through parse → serialize → parse', () => {
    const fm: NoteFm = {
      title: 't',
      visibility: 'public',
      scope_org_id: null,
      mode_hint: 'search',
      tags: ['x'],
    };
    const serialized = serializeNoteFm(fm, 'body content');
    const re = parseNoteFm(serialized);
    expect(re.fm).toEqual(fm);
    expect(re.body.trim()).toBe('body content');
  });
});
