import { DBFFile } from "dbffile";
import log from "electron-log/main";
import _ from "lodash";
import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
import errorTypeCheck from "../../util/errorTypeCheck";
import {
  DecodedPfl,
  JobLaborRateFields,
  DecodedPflLine,
} from "./decode-pfl.interface";
import { platform } from "@electron-toolkit/utils";
import { findFileCaseInsensitive } from "./decoder-utils";

const DecodePfl = async (
  extensionlessFilePath: string,
): Promise<DecodedPfl> => {
  let dbf: DBFFile | null = null;
  if (platform.isWindows) {
    try {
      dbf = await DBFFile.open(`${extensionlessFilePath}.PFL`);
    } catch (error) {
      //PFL File only has 1 location.
      log.error("Error opening PFL File.", errorTypeCheck(error));
    }

    if (!dbf) {
      log.error(`Could not find any PFL files at ${extensionlessFilePath}`);
      throw new Error(
        `Could not find any PFL files at ${extensionlessFilePath}`,
      );
    }
  } else {
    const possibleExtensions: string[] = [".pfl"];
    const filePath = await findFileCaseInsensitive(
      extensionlessFilePath,
      possibleExtensions,
    );
    try {
      if (!filePath) {
        log.error(`Could not find any PFL files at ${extensionlessFilePath}`);
        throw new Error(
          `Could not find any PFL files at ${extensionlessFilePath}`,
        );
      }
      dbf = await DBFFile.open(filePath);
    } catch (error) {
      log.error("Error opening PFL File.", errorTypeCheck(error));
      throw error;
    }
  }

  const rawDBFRecord = await dbf.readRecords();

  //AD2 will always have only 1 row.
  //Commented lines have been cross referenced with existing partner fields.

  const jobLaborRates: JobLaborRateFields = {
    rate_laa: 0,
    rate_lab: 0,
    rate_lad: 0,
    rate_las: 0,
    rate_lar: 0,
    rate_lae: 0,
    rate_lag: 0,
    rate_laf: 0,
    rate_lam: 0,
    rate_lau: 0,
    rate_la1: 0,
    rate_la2: 0,
    rate_la3: 0,
    rate_la4: 0,
  };

  const rawPflData: DecodedPflLine[] = rawDBFRecord.map((record) => {
    const singleLineData: DecodedPflLine = deepLowerCaseKeys(
      _.pick(record, [
        //TODO: Add typings for EMS File Formats.
        "LBR_TYPE",
        "LBR_DESC",
        "LBR_RATE",
        "LBR_TAX_IN",
        "LBR_TAXP",
        "LBR_ADJP",
        "LBR_TX_TY1",
        "LBR_TX_IN1",
        "LBR_TX_TY2",
        "LBR_TX_IN2",
        "LBR_TX_TY3",
        "LBR_TX_IN3",
        "LBR_TX_TY4",
        "LBR_TX_IN4",
        "LBR_TX_TY5",
        "LBR_TX_IN5",
      ]),
    );
    //Apply line by line adjustments.
    //Set the job.rate_<CIECA_TYPE> field based on the value.
    jobLaborRates[`rate_${singleLineData.lbr_type.toLowerCase()}`] =
      singleLineData.lbr_rate;

    //For Mitchell, Alum is stored under LA3 instead of LAA. Shift it back over.
    //The old partner had a check for this, but it always was true. Matching that logic.
    if (singleLineData.lbr_type === "LA3") {
      jobLaborRates[`rate_laa`] = singleLineData.lbr_rate;
    }

    //Also capture the whole object.
    //This is segmented because the whole object was not previously captured for ImEX as it wasn't needed.
    //Rome needs the whole object to accurately calculate the tax rates.

    return singleLineData;
  });

  //Apply business logic transfomrations.
  //We don't have an inspection date, we instead have `date_estimated`

  const pflObj = _.keyBy(rawPflData, "lbr_type");

  return { ...jobLaborRates, cieca_pfl: pflObj };
};

export default DecodePfl;
