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

const DecodeAD2 = async (
  extensionlessFilePath: string,
): Promise<DecodedAD2> => {
  let dbf: DBFFile | null = null;
  if (platform.isWindows) {
    try {
      dbf = await DBFFile.open(`${extensionlessFilePath}B.AD2`);
    } catch {
      dbf = await DBFFile.open(`${extensionlessFilePath}.AD2`);
    }

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

  const rawDBFRecord = await dbf.readRecords(1);

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

  const rawAd2Data: DecodedAD2 = deepLowerCaseKeys(
    _.pick(rawDBFRecord[0], [
      //TODO: Add typings for EMS File Formats.
      "CLMT_LN", //TODO: This claimant info shouldnt be passed back. Just for the owner info.
      "CLMT_FN",
      "CLMT_TITLE",
      "CLMT_CO_NM",
      "CLMT_ADDR1",
      "CLMT_ADDR2",
      "CLMT_CITY",
      "CLMT_ST",
      "CLMT_ZIP",
      "CLMT_CTRY",
      "CLMT_PH1",
      //"CLMT_PH1X",
      "CLMT_PH2",
      //"CLMT_PH2X",
      //"CLMT_FAX",
      //"CLMT_FAXX",
      "CLMT_EA",
      //"EST_CO_ID",
      "EST_CO_NM",
      "EST_ADDR1",
      "EST_ADDR2",
      "EST_CITY",
      "EST_ST",
      "EST_ZIP",
      "EST_CTRY",
      "EST_PH1",
      //"EST_PH1X",
      //"EST_PH2",
      //"EST_PH2X",
      //"EST_FAX",
      //"EST_FAXX",
      "EST_CT_LN",
      "EST_CT_FN",
      "EST_EA",
      //"EST_LIC_NO",
      //"EST_FILENO",
      //"INSP_CT_LN",
      //"INSP_CT_FN",
      //"INSP_ADDR1",
      //"INSP_ADDR2",
      //"INSP_CITY",
      //"INSP_ST",
      //"INSP_ZIP",
      //"INSP_CTRY",
      //"INSP_PH1",
      //"INSP_PH1X",
      //"INSP_PH2",
      //"INSP_PH2X",
      //"INSP_FAX",
      //"INSP_FAXX",
      //"INSP_EA",
      //"INSP_CODE",
      //"INSP_DESC",
      "INSP_DATE", //RENAME TO date_estimated
      //"INSP_TIME",
      //"RF_CO_ID",
      //"RF_CO_NM",
      //"RF_ADDR1",
      //"RF_ADDR2",
      //"RF_CITY",
      //"RF_ST",
      //"RF_ZIP",
      //"RF_CTRY",
      //"RF_PH1",
      //"RF_PH1X",
      //"RF_PH2",
      //"RF_PH2X",
      //"RF_FAX",
      //"RF_FAXX",
      //"RF_CT_LN",
      //"RF_CT_FN",
      //"RF_EA",
      //"RF_TAX_ID",
      //"RF_LIC_NO",
      //"RF_BAR_NO",
      //"RO_IN_DATE",
      //"RO_IN_TIME",
      //"TAR_DATE",
      //"TAR_TIME",
      //"RO_CMPDATE",
      //"RO_CMPTIME",
      //"DATE_OUT",
      //"TIME_OUT",
      //"RF_ESTIMTR",
      //"MKTG_TYPE",
      //"MKTG_SRC",
      //"LOC_NM",
      //"LOC_ADDR1",
      //"LOC_ADDR2",
      //"LOC_CITY",
      //"LOC_ST",
      //"LOC_ZIP",
      //"LOC_CTRY",
      //"LOC_PH1",
      //"LOC_PH1X",
      //"LOC_PH2",
      //"LOC_PH2X",
      //"LOC_FAX",
      //"LOC_FAXX",
      //"LOC_CT_LN",
      //"LOC_CT_FN",
      //"LOC_TITLE",
      //"LOC_PH",
      //"LOC_PHX",
      //"LOC_EA",
    ]),
  );

  //Apply business logic transfomrations.
  //We don't have an inspection date, we instead have `date_estimated`
  rawAd2Data.date_estimated = rawAd2Data.insp_date;
  delete rawAd2Data.insp_date;

  return rawAd2Data;
};
export default DecodeAD2;
