import {
  BaseAsset,
  RefObj,
  TestAsset,
  TestSpec,
} from "../../../model/assets-model.js";
import {
  checkForNullOrUndefined,
  isNullOrUndefined,
} from "../../common/data-helper.js";
import { AssetCacheModel } from "../../../model/asset-cache-model.js";
import { showError } from "./../../common/message-helper.js";
import { KindEnums } from "@apic/api-model/common/StudioEnums.js";

const addAssetRefValuesForTestKind = (
  refObjects: RefObj[],
  result: AssetCacheModel[],
  kind: KindEnums
) => {
  if (!isNullOrUndefined(refObjects)) {
    refObjects.forEach((refObj) => {
      if (!isNullOrUndefined(refObj.$ref)) {
        result.push({
          kind,
          ref: refObj.$ref,
          isNewlyAdded: true
        });
      }
    });
  }
};

const processReferences = (
  refContainer: any,
  result: AssetCacheModel[],
  kind: KindEnums
) => {
  if (!refContainer) return;

  // Format 1: Single reference with direct $ref property
  if (refContainer.$ref && typeof refContainer.$ref === 'string') {
    addAssetRefValuesForTestKind(
      [{ $ref: refContainer.$ref }],
      result,
      kind
    );
  }
  // Format 2: Multiple references with individual $ref properties (array of objects)
  else if (Array.isArray(refContainer)) {
    refContainer.forEach((item: any) => {
      if (item.$ref) {
        addAssetRefValuesForTestKind(
          [{ $ref: item.$ref }],
          result,
          kind
        );
      }
    });
  }
};

const getRefsFromTestAsset = (asset: BaseAsset): AssetCacheModel[] => {
  const testAsset = asset as unknown as TestAsset;
  const spec: TestSpec = testAsset.spec;
  const result: AssetCacheModel[] = [];
  try {
    checkForNullOrUndefined(testAsset, "Asset is null or undefined");

    // Process environment references
    processReferences(spec.environment, result, KindEnums.Environment);

    // Process assertion references in requests
    if (spec.request) {
      spec.request.forEach((request: any) => {
        if (request.assertions) {
          processReferences(request.assertions, result, KindEnums.Assertion);
        }
      });
    }

    return result;
  } catch (error: unknown) {
    showError((error as Error).message);
    return [];
  }
};

export { getRefsFromTestAsset };
