import { uniqBy } from "lodash";

/**
 * Get value from path
 * @param obj
 * @param path
 * @returns {*}
 */
const getValueFromPath = (obj, path) => path.split(".").reduce((prev, curr) => prev?.[curr], obj);

/**
 * Generate options from array
 * @param bodyshop
 * @param path
 * @returns {unknown[]}
 */
const generateOptionsFromArray = (bodyshop, path) => {
  const options = getValueFromPath(bodyshop, path);
  return uniqBy(
    options.map((value) => ({
      label: value,
      value: value
    })),
    "value"
  );
};

/**
 * Valid internal reflections
 * Note: This is intended for future functionality
 * @type {{special: string[], bodyshop: [{name: string, type: string}]}}
 */
const VALID_INTERNAL_REFLECTIONS = {
  bodyshop: [
    {
      name: "md_ro_statuses.statuses",
      type: "kv-to-v"
    }
  ]
};

/**
 * Generate options
 * @param bodyshop
 * @param path
 * @param labelPath
 * @param valuePath
 * @returns {{label: *, value: *}[]}
 */
const generateOptionsFromObject = (bodyshop, path, labelPath, valuePath) => {
  const options = getValueFromPath(bodyshop, path);
  return uniqBy(
    Object.values(options).map((value) => ({
      label: value[labelPath],
      value: value[valuePath]
    })),
    "value"
  );
};

/**
 * Generate special reflections
 * @param bodyshop
 * @param finalPath
 * @param t - i18n
 * @returns {{label: *, value: *}[]|{label: *, value: *}[]|{label: string, value: *}[]|*[]}
 */
const generateSpecialReflections = (bodyshop, finalPath, t) => {
  switch (finalPath) {
    case "payment_payers":
      return [
        {
          label: t("payments.labels.customer"),
          value: t("payments.labels.customer")
        },
        {
          label: t("payments.labels.insurance"),
          value: t("payments.labels.insurance")
        },
        // This is a weird one supposedly only used by one shop and could potentially be
        // placed behind a SplitSDK
        {
          label: t("payments.labels.external"),
          value: t("payments.labels.external")
        }
      ];
    case "payment_types":
      return generateOptionsFromArray(bodyshop, "md_payment_types");
    case "alt_transports":
      return generateOptionsFromArray(bodyshop, "appt_alt_transport");
    case "lost_sale_reasons":
      return generateOptionsFromArray(bodyshop, "md_lost_sale_reasons");
    // Special case because Referral Sources is an Array, not an Object.
    case "referral_source":
      return generateOptionsFromArray(bodyshop, "md_referral_sources");
    case "class":
      return generateOptionsFromArray(bodyshop, "md_classes");
    case "cost_centers":
      return generateOptionsFromObject(bodyshop, "md_responsibility_centers.costs", "name", "name");
    // Special case because Categories is an Array, not an Object.
    case "categories":
      return generateOptionsFromArray(bodyshop, "md_categories");
    case "insurance_companies":
      return generateOptionsFromObject(bodyshop, "md_ins_cos", "name", "name");
    case "employee_teams":
      return generateOptionsFromObject(bodyshop, "employee_teams", "name", "id");
    // Special case because Employees uses a concatenation of first_name and last_name
    case "employees": {
      const employeesOptions = getValueFromPath(bodyshop, "employees");
      return uniqBy(
        Object.values(employeesOptions).map((value) => ({
          label: `${value.first_name} ${value.last_name}`,
          value: value.id
        })),
        "value"
      );
    }
    case "last_names":
      return generateOptionsFromObject(bodyshop, "employees", "last_name", "last_name");
    case "first_names":
      return generateOptionsFromObject(bodyshop, "employees", "first_name", "first_name");
    case "job_statuses": {
      const statusOptions = getValueFromPath(bodyshop, "md_ro_statuses.statuses");
      return Object.values(statusOptions).map((value) => ({
        label: value,
        value
      }));
    }
    default:
      console.error("Invalid Special reflection provided by  Report Filters");
      return [];
  }
};

/**
 *  Generate bodyshop reflections
 * @param bodyshop
 * @param finalPath
 * @returns {{label: *, value: *}[]|*[]}
 */
const generateBodyshopReflections = (bodyshop, finalPath) => {
  const options = getValueFromPath(bodyshop, finalPath);
  const reflectionRenderer = VALID_INTERNAL_REFLECTIONS.bodyshop.find((reflection) => reflection.name === finalPath);
  if (reflectionRenderer?.type === "kv-to-v") {
    return Object.values(options).map((value) => ({
      label: value,
      value
    }));
  }
  return [];
};

/**
 * Generate internal reflections based on the path and bodyshop
 * @param bodyshop
 * @param upperPath
 * @param finalPath
 * @param t - i18n
 * @returns {{label: *, value: *}[]|[]|{label: *, value: *}[]|{label: string, value: *}[]|{label: *, value: *}[]|*[]}
 */
const generateInternalReflections = ({ bodyshop, upperPath, finalPath, t }) => {
  switch (upperPath) {
    case "special":
      return generateSpecialReflections(bodyshop, finalPath, t);
    case "bodyshop":
      return generateBodyshopReflections(bodyshop, finalPath);
    default:
      return [];
  }
};

export { generateInternalReflections };
