import { DBFFile } from "dbffile";
import log from "electron-log/main";
import _ from "lodash";
import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
import errorTypeCheck from "../../util/errorTypeCheck";
import store from "../store/store";
import { DecodedLin, DecodedLinLine } from "./decode-lin.interface";
import { platform } from "@electron-toolkit/utils";
import { findFileCaseInsensitive } from "./decoder-utils";

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

    if (!dbf) {
      log.error(`Could not find any LIN files at ${extensionlessFilePath}`);
      throw new Error(
        `Could not find any LIN files at ${extensionlessFilePath}`,
      );
    }
  } else {
    const possibleExtensions: string[] = ["lin"];
    const filePath = await findFileCaseInsensitive(
      extensionlessFilePath,
      possibleExtensions,
    );
    try {
      if (!filePath) {
        log.error(`Could not find any LIN files at ${extensionlessFilePath}`);
        throw new Error(
          `Could not find any LIN files at ${extensionlessFilePath}`,
        );
      }
      dbf = await DBFFile.open(filePath);
    } catch (error) {
      log.error("Error opening LIN 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 opCodeData = store.get("app.masterdata.opcodes"); //TODO: Type the op codes

  const rawLinData: DecodedLinLine[] = rawDBFRecord.map((record) => {
    const singleLineData: DecodedLinLine = deepLowerCaseKeys(
      _.pick(record, [
        //TODO: Add typings for EMS File Formats.
        "LINE_NO",
        "LINE_IND",
        "LINE_REF",
        "TRAN_CODE",
        "DB_REF",
        "UNQ_SEQ",
        // "WHO_PAYS",
        "LINE_DESC",
        "PART_TYPE",
        //TODO: Believe this was previously broken in partner. Need to confirm.
        // system == "M" ? "PART_DESCJ" : "PART_DES_J",
        //"PART_DESC_J",
        //End Check
        "GLASS_FLAG",
        "OEM_PARTNO",
        "PRICE_INC",
        "ALT_PART_I",
        "TAX_PART",
        "DB_PRICE",
        "ACT_PRICE",
        "PRICE_J",
        "CERT_PART",
        "PART_QTY",
        "ALT_CO_ID",
        "ALT_PARTNO",
        "ALT_OVERRD",
        "ALT_PARTM",
        "PRT_DSMK_P",
        "PRT_DSMK_M",
        "MOD_LBR_TY",
        "DB_HRS",
        "MOD_LB_HRS",
        "LBR_INC",
        "LBR_OP",
        "LBR_HRS_J",
        "LBR_TYP_J",
        "LBR_OP_J",
        "PAINT_STG",
        "PAINT_TONE",
        "LBR_TAX",
        "LBR_AMT",
        "MISC_AMT",
        "MISC_SUBLT",
        "MISC_TAX",
        "BETT_TYPE",
        "BETT_PCTG",
        "BETT_AMT",
        "BETT_TAX",
      ]),
    );
    //Apply line by line adjustments.
    singleLineData.op_code_desc = opCodeData[singleLineData.lbr_op]?.desc;

    return singleLineData;
  });

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

  return { joblines: { data: rawLinData } };
};
export default DecodeLin;
