import { describe, expect, it } from "vitest";
import type {
  CollectionSubject,
  SubjectLink,
  SubjectLinkKind,
} from "./subject-linkage-types";

describe("SubjectLinkKind", () => {
  it("accepts all valid kinds", () => {
    const kinds: SubjectLinkKind[] = ["self", "owner", "reference"];
    expect(kinds).toHaveLength(3);
  });
});

describe("SubjectLink type safety", () => {
  it("accepts a minimal self-link", () => {
    const link: SubjectLink = { field: "id", kind: "self" };
    expect(link.field).toBe("id");
    expect(link.kind).toBe("self");
    expect(link.target).toBeUndefined();
    expect(link.role).toBeUndefined();
  });

  it("accepts a reference link with target and role", () => {
    const link: SubjectLink = {
      field: "createdBy",
      kind: "reference",
      target: "users",
      role: "author",
    };
    expect(link.target).toBe("users");
    expect(link.role).toBe("author");
  });

  it("accepts an owner link with target", () => {
    const link: SubjectLink = {
      field: "userId",
      kind: "owner",
      target: "users",
    };
    expect(link.kind).toBe("owner");
    expect(link.target).toBe("users");
  });

  it("rejects a SubjectLink missing required field at compile time", () => {
    // @ts-expect-error — 'field' is required
    const _missing: SubjectLink = { kind: "self" };
    void _missing;
  });

  it("rejects a SubjectLink missing required kind at compile time", () => {
    // @ts-expect-error — 'kind' is required
    const _missing: SubjectLink = { field: "id" };
    void _missing;
  });
});

describe("CollectionSubject", () => {
  it("is assignable from a SubjectLink", () => {
    const subject: CollectionSubject = { field: "id", kind: "self" };
    expect(subject.kind).toBe("self");
  });

  it("accepts an array of CollectionSubject entries for multi-linkage", () => {
    const subjects: CollectionSubject[] = [
      { field: "id", kind: "self" },
      { field: "authorId", kind: "owner", target: "users" },
    ];
    expect(subjects).toHaveLength(2);
    expect(subjects[0]?.kind).toBe("self");
    expect(subjects[1]?.kind).toBe("owner");
  });
});
