import { describe, test } from "node:test";
import assert from "node:assert/strict";

import { parseProfile, serializeProfile } from "../src/profile.js";
import { SCHEMA_VERSION } from "../src/types.js";
import type { ProfileDoc, ProfileFact } from "../src/types.js";

const fact = (over: Partial<ProfileFact> = {}): ProfileFact => ({
  id: "abc123def456",
  value: "a value",
  first_seen: "2026-06-23",
  last_seen: "2026-06-23",
  evidence_count: 0,
  provenance: "human",
  status: "active",
  ...over,
});

describe("profile line-grammar (SC2)", () => {
  test("serialized text exposes both section headers", () => {
    const text = serializeProfile({ schemaVersion: SCHEMA_VERSION, static: [], dynamic: [] });
    assert.match(text, /^## Static$/m);
    assert.match(text, /^## Dynamic$/m);
    assert.match(text, /^schemaVersion: 1$/m);
  });

  test("parse ∘ serialize is identity over the whole doc", () => {
    const doc: ProfileDoc = {
      schemaVersion: SCHEMA_VERSION,
      static: [
        fact({ id: "0123456789ab", value: "Kjell Tore", provenance: "human" }),
        fact({ id: "fedcba987654", value: "", evidence_count: 3, provenance: "published" }),
      ],
      dynamic: [
        fact({ id: "aaaabbbbcccc", value: "leans contrarian", status: "superseded", last_seen: "2026-06-20" }),
      ],
    };
    assert.deepEqual(parseProfile(serializeProfile(doc)), doc);
  });

  test("a value containing ], | and quotes round-trips intact", () => {
    const tricky = 'uses "scare quotes" | pipes | and a ] bracket';
    const doc: ProfileDoc = {
      schemaVersion: SCHEMA_VERSION,
      static: [fact({ value: tricky })],
      dynamic: [],
    };
    const round = parseProfile(serializeProfile(doc));
    assert.equal(round.static[0].value, tricky);
    assert.deepEqual(round, doc);
  });

  test("an empty-value fact round-trips to an empty string (the source-absent case)", () => {
    const doc: ProfileDoc = {
      schemaVersion: SCHEMA_VERSION,
      static: [fact({ value: "" })],
      dynamic: [],
    };
    const round = parseProfile(serializeProfile(doc));
    assert.equal(round.static[0].value, "");
    assert.deepEqual(round, doc);
  });

  test("section attribution is preserved (static vs dynamic do not bleed)", () => {
    const doc: ProfileDoc = {
      schemaVersion: SCHEMA_VERSION,
      static: [fact({ id: "111111111111", value: "static one" })],
      dynamic: [fact({ id: "222222222222", value: "dynamic one" })],
    };
    const round = parseProfile(serializeProfile(doc));
    assert.equal(round.static.length, 1);
    assert.equal(round.dynamic.length, 1);
    assert.equal(round.static[0].value, "static one");
    assert.equal(round.dynamic[0].value, "dynamic one");
  });

  test("an unsupported schemaVersion throws", () => {
    assert.throws(() => parseProfile("# Profile\n\nschemaVersion: 99\n\n## Static\n\n## Dynamic\n"));
  });
});
