/**
 * Copyright Super iPaaS Integration LLC, an IBM Company 2024
 */
import { getRefsFromApiAsset } from "./api-asset-handler.js";
import { BaseAsset } from "../model/assets-model.js";
import { showWarning } from "../helpers/common/message-helper.js";
import { AssetCache } from "../cache/asset-cache.js";

jest.mock("../helpers/common/message-helper.js", () => ({
  showWarning: jest.fn(),
  showError: jest.fn(),
  showSuccess: jest.fn(),
  showInfo: jest.fn(),
  showMessage: jest.fn(),
}));

jest.mock("../cache/asset-cache.js", () => ({
  AssetCache: {
    getInstance: jest.fn(() => ({
      getProjectNames: jest.fn(() => "test-project"),
      getRootDirPath: jest.fn(() => "/mock/root/path"),
    })),
  },
}));

jest.mock("../helpers/apim/root-dir-helper.js", () => ({
  getOtherProjectsNames: jest.fn(() => new Set()),
}));

jest.mock("../helpers/common/fs-helper.js", () => ({
  getSubDirectory: jest.fn((root, project) => `${root}/${project}`),
  isDirectory: jest.fn(() => true),
}));

jest.mock("../helpers/apim/build-helper.js", () => ({
  searchAsset: jest.fn(() => true),
}));

describe("api asset handler function test suite", () => {
  const mockBaseAsset: BaseAsset = {
    metadata: {
      name: "test-asset",
    },
    spec: {
      "policy-sequence": [{ $ref: "policy-seq-1" }, { $ref: "policy-seq-2" }],
    },
  } as unknown as BaseAsset;

  it("should return target assets from policy sequences", () => {
    const expectedTargetAssets = [
      { kind: "DataPowerAssembly", ref: "policy-seq-1", isNewlyAdded: true },
      { kind: "DataPowerAssembly", ref: "policy-seq-2", isNewlyAdded: true },
    ];

    const result = getRefsFromApiAsset(mockBaseAsset);

    expect(result).toEqual(expectedTargetAssets);
  });

  it("should handle empty policy-seq array", () => {
    const emptyPolicySeqAsset: BaseAsset = {
      metadata: {
        name: "test-asset",
      },
      spec: {
        "policy-sequence": [],
      },
    } as unknown as BaseAsset;

    const result = getRefsFromApiAsset(emptyPolicySeqAsset);

    expect(result).toEqual([]);
  });

  it("should show warning if spec is not defined", () => {
    const assetWithUndefinedSpec: BaseAsset = {
      metadata: {
        name: "test-asset",
      },
      spec: undefined,
    } as unknown as BaseAsset;

    getRefsFromApiAsset(assetWithUndefinedSpec);

    expect(showWarning).toHaveBeenCalledWith(
      "Spec is not defined for the asset with kind 'API' and name 'test-asset'"
    );
  });
  it("should handle asset without spec property", () => {
    const assetWithoutSpec: BaseAsset = {
      metadata: {
        name: "test-asset",
      },
    } as unknown as BaseAsset;

    const result = getRefsFromApiAsset(assetWithoutSpec);

    expect(result).toEqual([]);
    expect(showWarning).toHaveBeenCalledWith(
      "Spec is not defined for the asset with kind 'API' and name 'test-asset'"
    );
  });
  it("should handle multiple assets in policy-seq", () => {
    const multiplePolicySeqAsset: BaseAsset = {
      metadata: {
        name: "test-asset",
      },
      spec: {
        "policy-sequence": [
          { $ref: "policy-seq-1" },
          { $ref: "policy-seq-2" },
          { $ref: "policy-seq-3" },
          { $ref: "policy-seq-4" },
        ],
      },
    } as unknown as BaseAsset;

    const expectedTargetAssets = [
      { kind: "DataPowerAssembly", ref: "policy-seq-1", isNewlyAdded: true },
      { kind: "DataPowerAssembly", ref: "policy-seq-2", isNewlyAdded: true },
      { kind: "DataPowerAssembly", ref: "policy-seq-3", isNewlyAdded: true },
      { kind: "DataPowerAssembly", ref: "policy-seq-4", isNewlyAdded: true },
    ];

    const result = getRefsFromApiAsset(multiplePolicySeqAsset);

    expect(result).toEqual(expectedTargetAssets);
  });

  it("should ignore extra properties in policy-seq", () => {
    const assetWithExtraProps: BaseAsset = {
      metadata: {
        name: "test-asset",
      },
      spec: {
        "policy-sequence": [
          { $ref: "policy-seq-1", extraProp: "extraValue" },
          { $ref: "policy-seq-2", anotherProp: "anotherValue" },
        ],
      },
    } as unknown as BaseAsset;

    const expectedTargetAssets = [
      { kind: "DataPowerAssembly", ref: "policy-seq-1", isNewlyAdded: true },
      { kind: "DataPowerAssembly", ref: "policy-seq-2", isNewlyAdded: true },
    ];

    const result = getRefsFromApiAsset(assetWithExtraProps);

    expect(result).toEqual(expectedTargetAssets);
  });

  it("should handle empty metadata", () => {
    const assetWithEmptyMetadata: BaseAsset = {
      metadata: {},
      spec: {
        "policy-sequence": [{ $ref: "policy-seq-1" }],
      },
    } as unknown as BaseAsset;

    const expectedTargetAssets = [
      { kind: "DataPowerAssembly", ref: "policy-seq-1", isNewlyAdded: true },
    ];

    const result = getRefsFromApiAsset(assetWithEmptyMetadata);

    expect(result).toEqual(expectedTargetAssets);
  });

});
