import { describe, test, expect } from "bun:test";
import { CredentialTypeController } from "../../../src/controllers/CredentialTypeController";
import { buildMockCredentialType } from "../../setup";
import { ValueType } from "../../../src/modules/credentials/credentialTypeDefs";

describe("CredentialTypeController", () => {
  // -------------------------------------------------------------------
  // Constructor
  // -------------------------------------------------------------------
  describe("constructor", () => {
    test("sets public properties", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      expect(ctrl.id).toBe("ctype-1");
      expect(ctrl.name).toBe("Login Credential");
      expect(ctrl.permissionScope).toBe("credential.login");
      expect(ctrl.icon).toBeNull();
      expect(ctrl.fields).toHaveLength(2);
    });

    test("parses timestamps", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      expect(ctrl.createdAt).toBeInstanceOf(Date);
      expect(ctrl.updatedAt).toBeInstanceOf(Date);
    });
  });

  // -------------------------------------------------------------------
  // getFieldDefinition
  // -------------------------------------------------------------------
  describe("getFieldDefinition()", () => {
    test("returns matching field", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      const field = ctrl.getFieldDefinition("username");
      expect(field).toBeDefined();
      expect(field!.name).toBe("Username");
    });

    test("returns undefined for unknown field", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      expect(ctrl.getFieldDefinition("nonexistent")).toBeUndefined();
    });
  });

  // -------------------------------------------------------------------
  // getRequiredFields
  // -------------------------------------------------------------------
  describe("getRequiredFields()", () => {
    test("returns only required fields", () => {
      const data = buildMockCredentialType({
        fields: [
          {
            id: "a",
            name: "A",
            required: true,
            secure: false,
            valueType: ValueType.PLAIN_TEXT,
          },
          {
            id: "b",
            name: "B",
            required: false,
            secure: false,
            valueType: ValueType.PLAIN_TEXT,
          },
          {
            id: "c",
            name: "C",
            required: true,
            secure: true,
            valueType: ValueType.PASSWORD,
          },
        ],
      });
      const ctrl = new CredentialTypeController(data);
      const required = ctrl.getRequiredFields();
      expect(required).toHaveLength(2);
      expect(required.map((f) => f.id)).toEqual(["a", "c"]);
    });
  });

  // -------------------------------------------------------------------
  // getSecureFields
  // -------------------------------------------------------------------
  describe("getSecureFields()", () => {
    test("returns only secure fields", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      const secure = ctrl.getSecureFields();
      expect(secure).toHaveLength(1);
      expect(secure[0]!.id).toBe("password");
    });
  });

  // -------------------------------------------------------------------
  // countCredentials
  // -------------------------------------------------------------------
  describe("countCredentials()", () => {
    test("returns 0 when no credentials", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      expect(ctrl.countCredentials()).toBe(0);
    });

    test("returns correct count", () => {
      const data = buildMockCredentialType({
        credentials: [{ id: "c1" }, { id: "c2" }, { id: "c3" }],
      });
      const ctrl = new CredentialTypeController(data);
      expect(ctrl.countCredentials()).toBe(3);
    });
  });

  // -------------------------------------------------------------------
  // toJson
  // -------------------------------------------------------------------
  describe("toJson()", () => {
    test("returns base JSON without credential count by default", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      const json = ctrl.toJson();
      expect(json.id).toBe("ctype-1");
      expect(json.name).toBe("Login Credential");
      expect(json.credentialCount).toBeUndefined();
    });

    test("includes credential count when option is set", () => {
      const data = buildMockCredentialType({
        credentials: [{ id: "c1" }, { id: "c2" }],
      });
      const ctrl = new CredentialTypeController(data);
      const json = ctrl.toJson({ includeCredentialCount: true });
      expect(json.credentialCount).toBe(2);
    });

    test("includes all expected keys", () => {
      const ctrl = new CredentialTypeController(buildMockCredentialType());
      const json = ctrl.toJson();
      expect(json).toHaveProperty("id");
      expect(json).toHaveProperty("name");
      expect(json).toHaveProperty("permissionScope");
      expect(json).toHaveProperty("icon");
      expect(json).toHaveProperty("fields");
      expect(json).toHaveProperty("createdAt");
      expect(json).toHaveProperty("updatedAt");
    });
  });
});
