import fs from "fs";
import path from "path";
import { describe, it, expect } from "vitest";
import { TotalsServerSide as TotalsServerSideCA } from "../job-totals"; // Canadian version (imex)
import { TotalsServerSide as TotalsServerSideUS } from "../job-totals-USA";
import { isFunction } from "lodash"; // US version (rome)

/**
 * This function is used to replace the values in the object with their toObject() representation.
 * @param key
 * @param value
 * @returns {*}
 */
const dineroReplacer = (key, value) => {
  if (isFunction(value)) {
    return value.toObject();
  }
  return value;
};

/**
 * Normalizes the output of the TotalsServerSide function by converting
 * @param obj
 * @returns {any}
 */
const normalizeOutput = (obj) => {
  return JSON.parse(JSON.stringify(obj, dineroReplacer));
};

/**
 * This test suite is designed to validate the functionality of the TotalsServerSide function
 */
describe("TotalsServerSide fixture tests", () => {
  const fixturesDir = path.join(__dirname, "fixtures", "job-totals");

  const fixtureFiles = fs.readdirSync(fixturesDir).filter((f) => f.endsWith(".json"));

  if (fixtureFiles.length === 0) {
    it.skip("skips when no job total fixtures are present", () => {});
    return;
  }

  const dummyClient = {
    request: async () => {
      return {};
    }
  };

  const dummyRes = {
    status: () => ({ send: () => {} })
  };

  fixtureFiles.forEach((file) => {
    it(`should produce matching output for fixture file ${file}`, async () => {
      const fixturePath = path.join(fixturesDir, file);
      const fixtureData = JSON.parse(fs.readFileSync(fixturePath, "utf8"));

      const { environment, input, output: expectedOutput } = fixtureData;

      const req = {
        body: {
          job: input,
          client: dummyClient
        },
        user: {}
      };

      const computedOutput =
        environment === "us" ? await TotalsServerSideUS(req, dummyRes) : await TotalsServerSideCA(req, dummyRes);

      const normalizedComputed = normalizeOutput(computedOutput);
      const normalizedExpected = normalizeOutput(expectedOutput);

      expect(normalizedComputed).toEqual(normalizedExpected);
    });
  });
});
