import { describe, test, expect } from "bun:test";
import { CompanyController } from "../../../src/controllers/CompanyController";
import { buildMockCompany } from "../../setup";

const mockCwData = {
  company: {
    addressLine1: "123 Main St",
    addressLine2: null,
    city: "Springfield",
    state: "IL",
    zip: "62701",
    country: { name: "United States" },
    _info: { contacts_href: "" },
  } as any,
  defaultContact: {
    id: 100,
    firstName: "John",
    lastName: "Doe",
    inactiveFlag: false,
    title: "CEO",
    defaultPhoneNbr: "555-1234",
    communicationItems: [
      { type: { name: "Email" }, value: "john@test.com" },
      { type: { name: "Phone" }, value: "555-1234" },
    ],
  } as any,
  allContacts: [] as any[],
};

describe("CompanyController", () => {
  // -------------------------------------------------------------------
  // Constructor
  // -------------------------------------------------------------------
  describe("constructor", () => {
    test("sets public properties from company data", () => {
      const data = buildMockCompany();
      const ctrl = new CompanyController(data);
      expect(ctrl.id).toBe("company-1");
      expect(ctrl.name).toBe("Test Company");
      expect(ctrl.cw_Identifier).toBe("TestCo");
      expect(ctrl.cw_CompanyId).toBe(123);
    });

    test("accepts optional CW data", () => {
      const data = buildMockCompany();
      const ctrl = new CompanyController(data, mockCwData);
      expect(ctrl.cw_Data).toBeDefined();
      expect(ctrl.cw_Data?.company.city).toBe("Springfield");
    });

    test("cw_Data is undefined when not provided", () => {
      const data = buildMockCompany();
      const ctrl = new CompanyController(data);
      expect(ctrl.cw_Data).toBeUndefined();
    });
  });

  // -------------------------------------------------------------------
  // toJson
  // -------------------------------------------------------------------
  describe("toJson()", () => {
    test("returns base fields without options", () => {
      const ctrl = new CompanyController(buildMockCompany(), mockCwData);
      const json = ctrl.toJson();
      expect(json.id).toBe("company-1");
      expect(json.name).toBe("Test Company");
      expect(json.cw_Identifier).toBe("TestCo");
      expect(json.cw_CompanyId).toBe(123);
    });

    test("excludes address when includeAddress is false", () => {
      const ctrl = new CompanyController(buildMockCompany(), mockCwData);
      const json = ctrl.toJson({
        includeAddress: false,
        includePrimaryContact: false,
      });
      expect(json.cw_Data.address).toBeUndefined();
    });

    test("includes address when includeAddress is true", () => {
      const ctrl = new CompanyController(buildMockCompany(), mockCwData);
      const json = ctrl.toJson({
        includeAddress: true,
        includePrimaryContact: false,
      });
      expect(json.cw_Data.address).toBeDefined();
      expect(json.cw_Data.address!.city).toBe("Springfield");
      expect(json.cw_Data.address!.state).toBe("IL");
    });

    test("includes primary contact when includePrimaryContact is true", () => {
      const ctrl = new CompanyController(buildMockCompany(), mockCwData);
      const json = ctrl.toJson({
        includeAddress: false,
        includePrimaryContact: true,
      });
      expect(json.cw_Data.primaryContact).toBeDefined();
      expect(json.cw_Data.primaryContact!.firstName).toBe("John");
      expect(json.cw_Data.primaryContact!.lastName).toBe("Doe");
      expect(json.cw_Data.primaryContact!.email).toBe("john@test.com");
    });

    test("excludes primary contact when includePrimaryContact is false", () => {
      const ctrl = new CompanyController(buildMockCompany(), mockCwData);
      const json = ctrl.toJson({
        includeAddress: false,
        includePrimaryContact: false,
      });
      expect(json.cw_Data.primaryContact).toBeUndefined();
    });

    test("includes allContacts when includeAllContacts is true", () => {
      const cwDataWithContacts = {
        ...mockCwData,
        allContacts: [
          {
            id: 200,
            firstName: "Jane",
            lastName: "Smith",
            inactiveFlag: false,
            title: "CTO",
            defaultPhoneNbr: "555-5678",
            communicationItems: [
              { type: { name: "Email" }, value: "jane@test.com" },
            ],
          } as any,
        ],
      };
      const ctrl = new CompanyController(
        buildMockCompany(),
        cwDataWithContacts,
      );
      const json = ctrl.toJson({
        includeAddress: false,
        includePrimaryContact: false,
        includeAllContacts: true,
      });
      expect(json.cw_Data.allContacts).toBeDefined();
      expect(json.cw_Data.allContacts).toHaveLength(1);
      expect(json.cw_Data.allContacts![0]!.firstName).toBe("Jane");
    });

    test("email is null when no Email communication item", () => {
      const noEmailCw = {
        ...mockCwData,
        defaultContact: {
          ...mockCwData.defaultContact,
          communicationItems: [{ type: { name: "Phone" }, value: "555" }],
        },
      };
      const ctrl = new CompanyController(buildMockCompany(), noEmailCw);
      const json = ctrl.toJson({
        includeAddress: false,
        includePrimaryContact: true,
      });
      expect(json.cw_Data.primaryContact!.email).toBeNull();
    });

    test("email is null when communicationItems is missing", () => {
      const noCIData = {
        ...mockCwData,
        defaultContact: {
          ...mockCwData.defaultContact,
          communicationItems: undefined,
        },
      };
      const ctrl = new CompanyController(buildMockCompany(), noCIData);
      const json = ctrl.toJson({
        includeAddress: false,
        includePrimaryContact: true,
      });
      expect(json.cw_Data.primaryContact!.email).toBeNull();
    });

    test("country defaults to United States when null", () => {
      const noCntry = {
        ...mockCwData,
        company: { ...mockCwData.company, country: null },
      };
      const ctrl = new CompanyController(buildMockCompany(), noCntry);
      const json = ctrl.toJson({
        includeAddress: true,
        includePrimaryContact: false,
      });
      expect(json.cw_Data.address!.country).toBe("United States");
    });
  });
});
