const fs = require("fs");
const docClassifer = require("./docClassifier.js");
//const checkService = require("../checkService/checkService.js");
const modelController = require("../agent/ModelController.js");
const { updateDB } = require("../firebase/firebase.js");
const { v4: uuidv4 } = require("uuid");
const path = require("path");
const { count } = require("firebase/firestore");

async function readDir(direcPath, folder, countObject) {
  const fdirup = path.join(
    __dirname,
    "..",
    "Documents",
    "Textfiles",
    `${folder}`
  );

  try {
    const dirArray = countObject.files.map((file) => {
      return `${fdirup}/${file.split(".")[0]}.txt`;
    });

    const sortedFilePaths = dirArray.sort();
    const docType = await docClassifer.classifyDoc(sortedFilePaths, folder);
    console.log("====================================== docParser readDir");
    let parseOneCount = 0;
    methodSelector(
      docType,
      sortedFilePaths,
      folder,
      parseOneCount,
      countObject
    );
  } catch (err) {
    console.log("read error", err);
  }
}

async function methodSelector(
  docType,
  filePaths,
  folder,
  parseOneCount,
  countObject
) {
  let searchStr;
  let determinedDocType;

  if (docType.combined === "combined-numbered") {
    determinedDocType = "combined-numbered";
    const isRequests = true;
    console.log(
      "=========================================determinedDocType in docParser methodSelecotr",
      determinedDocType
    );
    updateDB(docId, determinedDocType);
    modelController.createArrayOfQuestions(
      folder,
      determinedDocType,
      isRequests,
      countObject
    );
    return;
  } else if (docType.rogs > docType.docProd && docType.rogs > docType.admit) {
    determinedDocType = "interrogatories";
    let parseRogsCount = 0;
    parseRogs(docType, filePaths, folder, determinedDocType, parseRogsCount);
  } else if (
    docType.docProd > docType.rogs &&
    docType.docProd > docType.admit
  ) {
    determinedDocType = "production";
    parseProdCount = 0;
    parseProduction(
      docType,
      filePaths,
      folder,
      parseOneCount,
      determinedDocType,
      parseProdCount
    );
    return;
  } else if (docType.admit > docType.rogs && docType.admit > docType.docProd) {
    determinedDocType = "admissions";
    let parseAdmitCount = 0;
    parseAdmissions(
      docType,
      filePaths,
      folder,
      parseOneCount,
      determinedDocType,
      parseAdmitCount
    );
    return;
  } else if (
    docType.combined > docType.rogs &&
    docType.combined > docType.docProd &&
    docType.combined > docType.admit
  ) {
    // maybe deprecate
    determinedDocType = "combined";
    parseCombined(docType, filePaths, folder, parseOneCount, determinedDocType);
  } else {
    //  To avoid undefined errors in later checks (for now)
    searchStr = "N~U**LL";
  }
  return determinedDocType;
}

/*******************************************************************************
 *
 *  Combined (Interrogatories and Requests for Production) Request parser
 *
 *******************************************************************************/

async function parseCombined(
  docType,
  filePaths,
  folder,
  parseOneCount,
  determinedDocType,
  parseCombinedCount
) {
  const processArray = [];
  const rogs = [];

  filePaths.forEach((filePath) => {
    fileData = fs.readFileSync(filePath, "utf8", function (err) {
      console.log("error in readFile", err);
    });
    const arr = [];
    searchStr = 1;

    const stringChunk = fileData.toString().toLowerCase();

    const string = fileData.toString().toLowerCase();
    for (
      let pos = stringChunk.lastIndexOf(`${searchStr.toString()}.`);
      pos > -1;
      pos = stringChunk.indexOf(`${searchStr.toString()}.`, pos + 1)
    ) {
      arr.push(pos);
      searchStr++;
      console.log("arr, pos", arr, pos);
    }

    const questionsArray = arr.map((item, i) => {
      return string.slice(arr[i], arr[i + 1]);
    });
    const clean = questionsArray.map((item) => {
      return item.replace(/\r?\n|\r/g, "");
    });

    processArray.push(...clean);

    const unique = processArray.filter(function (item, pos) {
      return processArray.indexOf(item) == pos;
    });

    unique.forEach((item) => {
      let obj = {};
      const requestId = uuidv4();
      obj["requestId"] = requestId;
      obj["text"] = item;
      rogs.push(obj);
    });

    if (rogs.length < 3) {
    } else {
      makeDir(folder, determinedDocType);
      let requestArray = [];
      let requestObject = {};
      requestObject["type"] = determinedDocType;
      requestObject["requests"] = rogs;
      requestArray.push(requestObject);
      saveParsedRogs(requestArray, folder, determinedDocType);
    }
  });
  return;
}

/*******************************************************************************
 *
 *  Request for production of documents parser
 *
 *******************************************************************************/

async function parseProduction(
  docType,
  filePaths,
  folder,
  parseOneCount,
  determinedDocType,
  parseProdCount
) {
  const initialHeaderString = "requests for production"; // /^request* for admission*$/;

  const processArray = [];
  const rogs = [];
  let searchStr;
  if (parseProdCount < 1) {
    searchStr = "REQUEST FOR PRODUCTION";
  } else if (parseProdCount === 1) {
    searchStr = "REQUEST NO";
  } else if (parseProdCount === 2) {
    searchStr = "REQUEST NUM";
  }

  filePaths.forEach((filePath, mainIndex) => {
    let fileData;
    fileData = fs.readFileSync(filePath, "utf8");
    const arr = [];

    const stringChunk = fileData.toString().toLowerCase();
    const string = fileData.toString().toLowerCase();

    for (
      let pos = stringChunk.indexOf(searchStr.toLowerCase());
      pos > -1;
      pos = stringChunk.indexOf(searchStr.toLowerCase(), pos + 1)
    ) {
      arr.push(pos);
    }

    const questionsArray = arr.map((item, i) => {
      return string.slice(arr[i], arr[i + 1]);
    });
    const clean = questionsArray.map((item) => {
      return item.replace(/\r?\n|\r/g, "");
    });
    processArray.push(...clean);
  });

  const unique = processArray.filter(function (item, pos) {
    return processArray.indexOf(item) == pos;
  });

  unique.forEach((item) => {
    let obj = {};
    const requestId = uuidv4();
    obj["requestId"] = requestId;
    obj["text"] = item;
    rogs.push(obj);
  });

  if (rogs.length < 2) {
    if (parseProdCount < 2) {
      parseProdCount++;
      parseProduction(
        docType,
        filePaths,
        folder,
        parseOneCount,
        determinedDocType,
        parseProdCount
      );
    } else {
      determinedDocType = "combined-numbered";
      const isRequests = true;
      modelController.createArrayOfQuestions(
        folder,
        determinedDocType,
        isRequests
      );
      return;
    }
  } else {
    const docId = folder;
    const reqType = "production"; //determinedDocType var value is lost by here not sure why but this hack should fix
    const directionVar = "Requests";
    const saveDirectory = path.join(
      __dirname,
      "..",
      "Documents",
      `${directionVar}`,
      `${reqType}`,
      `${docId}`
    );
    fs.mkdir(`${saveDirectory}`, function (err) {
      if (err) {
        console.log("makeDir utilities error creating directory: " + err);
      }
    });
    let requestArray = [];
    let requestObject = {};
    requestObject["type"] = determinedDocType;
    requestObject["requests"] = rogs;
    requestArray.push(requestObject);
    const fileSuffix = "-jbk-parsedRequests.json";
    const data = JSON.stringify(requestArray);
    fs.writeFile(
      `${saveDirectory}/${docId}${fileSuffix}`,
      data,
      function (err) {
        if (err) {
          return console.log("Error in parseProd writeFile:", err);
        }
      }
    );
  }
}

/*******************************************************************************
 *
 *  Requests for Admissions parser
 *
 *******************************************************************************/

async function parseAdmissions(
  docType,
  filePaths,
  folder,
  parseOneCount,
  determinedDocType,
  parseAdmitCount
) {
  const initialHeaderString = "requests for admissions"; //^request* for admission*$/;
  console.log(
    "parseAdmissions called-------------------------------------------"
  );
  const processArray = [];
  const rogs = [];
  let searchStr;
  if (parseAdmitCount < 1) {
    searchStr = "REQUEST NO";
  } else if (parseAdmitCount === 1) {
    searchStr = "ADMIT THAT";
  } else if (parseAdmitCount === 2) {
    searchStr = "ADMIT";
  } else if (parseAdmitCount === 3) {
    regex = /^[1-9]?$/;
    searchStr = `Request No. ${reggex}`;
  } else if (parseAdmitCount === 4) {
    regex = /^[1-9][0-9]?$/;
    searchStr = `Request No. ${reggex}`;
  } else if (parseAdmitCount === 5) {
    regex = /^[1-9]?$/;
    searchStr = `Request ${reggex}.`;
  } else {
    regex = /^[1-9][0-9]?$/;
    searchStr = `Request ${reggex}.`;
  }

  filePaths.forEach((filePath, mainIndex) => {
    let fileData;
    fileData = fs.readFileSync(filePath, "utf8");
    const arr = [];

    const stringChunk = fileData.toString().toLowerCase();
    //const string = fileData.toString().toLowerCase();  this might solve lowercase problem
    const string = fileData.toString();
    for (
      let pos = stringChunk.indexOf(searchStr.toLowerCase());
      pos > -1;
      pos = stringChunk.indexOf(searchStr.toLowerCase(), pos + 1)
    ) {
      arr.push(pos);
    }

    const questionsArray = arr.map((item, i) => {
      return string.slice(arr[i], arr[i + 1]);
    });
    const clean = questionsArray.map((item) => {
      let temp4;
      const temp = item.replace(/\r?\n|\r/g, "");
      const temp2 = temp.replace("request no.", "").trim();
      const temp3 = temp2.replace("REQUEST NO.", "").trim();
      const firstChar = Number(temp3[0]);
      if (Number.isInteger(firstChar)) {
        temp4 = temp3.substring(3);
        char = temp3[2].toUpperCase();
        return `${char}${temp4}`;
      } else {
        return temp2;
      }
    });
    processArray.push(...clean);
  });

  const unique = processArray.filter(function (item, pos) {
    return processArray.indexOf(item) == pos;
  });

  unique.forEach((item) => {
    let obj = {};
    const requestId = uuidv4();
    obj["requestId"] = requestId;
    obj["text"] = item;
    rogs.push(obj);
  });

  if (rogs.length < 2) {
    console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>rogs.length < 2 fired");
    if (parseAdmitCount < 6) {
      console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>parseAdmitCount < 6 fired");
      let determinedDocType = "admissions";
      parseAdmitCount++;
      parseAdmissions(
        docType,
        filePaths,
        folder,
        parseOneCount,
        determinedDocType,
        parseAdmitCount
      );
    } else {
      console.log(
        "--------------------> Parsed admissions switching to LLM calling createArrayOfQuestions"
      );
      const isRequests = true;
      determinedDocType = "combined-numbered";
      updateDB(docId, determinedDocType);
      modelController.createArrayOfQuestions(
        folder,
        determinedDocType,
        isRequests
      );
    }
  } else {
    const reqType = "admissions"; //determinedDocType var value is lost by here not sure why but this hack should fix
    const directionVar = "Requests";
    const docId = folder;
    const saveDirectory = path.join(
      __dirname,
      "..",
      "Documents",
      "Requests",
      "admissions",
      `${docId}`
    );

    fs.mkdir(`${saveDirectory}`, function (err) {
      if (err) {
        console.log("makeDir utilities error creating directory: " + err);
      }
    });
    let requestArray = [];
    let requestObject = {};
    requestObject["type"] = determinedDocType;
    requestObject["requests"] = rogs;
    requestArray.push(requestObject);
    parseTextFiles2SaveCount = 0;
    parseAdmitCount = 0;
    console.log("requestArray", requestArray);
    const data = JSON.stringify(requestArray);
    const fileSuffix = "-jbk-parsedRequests.json";

    fs.writeFile(
      `${saveDirectory}/${docId}${fileSuffix}`,
      data,
      function (err) {
        if (err) {
          return console.log("Error in parse admit writeFile:", err);
        }
      }
    );
    const reqstType = "admissions";
    const isRequests = true;
    function sleep(ms) {
      return new Promise((resolve) => setTimeout(resolve, ms));
    }
    await sleep(3000);
    modelController.arrayGenAnswers(docId, reqstType, isRequests);
  }
}

/*******************************************************************************
 *
 *  Interrogatory Parser
 *
 *******************************************************************************/

async function parseRogs(
  docType,
  filePaths,
  folder,
  determinedDocType,
  parseRogsCount
) {
  let searchStr;
  console.log(
    "***************************************************************************** PARSE ROGS FIRED"
  );
  if (parseRogsCount < 1) {
    searchStr = "INTERROGATORY NO";
  } else {
    searchStr = "INTERROGATORY NUM";
  }
  const processArray = [];
  const rogs = [];
  filePaths.forEach((filePath) => {
    let fileData = fs.readFileSync(filePath, "utf8");
    const arr = [];

    if (fileData) {
      if (!fileData.toLowerCase().includes(searchStr.toLowerCase())) return;
    }

    const string = fileData.toString();

    for (
      let pos = fileData.toLowerCase().indexOf(searchStr.toLowerCase());
      pos > -1;
      pos = fileData.toLowerCase().indexOf(searchStr.toLowerCase(), pos + 1)
    ) {
      arr.push(pos);
    }

    const questionsArray = arr.map((item, i) => {
      return string.slice(arr[i], arr[i + 1]);
    });

    const clean = questionsArray.map((item) => {
      return item.replace(/\r?\n|\r/g, "");
    });
    processArray.push(...clean);
  });

  const unique = processArray.filter(function (item, pos) {
    return processArray.indexOf(item) == pos;
  });

  const regex = /[A-Za-z]+ [A-Za-z]+\. [A-Za-z0-9]+:/;
  const regex2 = new RegExp(/.[Pp]age\s\d{1,2}$/);
  const tempArr = unique.map((item) => {
    function capitalizeFirstLetter(string) {
      return string.charAt(0).toUpperCase() + string.slice(1);
    }
    const scrubbed = item.replace(regex, "");
    const scrubbedMore = scrubbed.replace(regex2, ".");
    const caps = capitalizeFirstLetter(scrubbedMore);
    return caps;
  });

  tempArr.forEach((item) => {
    let obj = {};
    const interrogatoryId = uuidv4();
    obj["interrogatoryId"] = interrogatoryId;
    obj["text"] = item;
    rogs.push(obj);
  });

  if (rogs.length < 2) {
    if (parseRogsCount < 2) {
      parseRogsCount++;
      parseRogs(docType, filePaths, folder, determinedDocType, parseRogsCount);
    } else {
      const _isRequests = true;
      const reqType = "combined-numbered";
      console.log(
        "---- ----  ---- ----  ---- ----  ---- ----  ---- ----  ---- ---- parseRogs GIVING UP calling createArrayOfQuestions ---- ---- "
      );
      modelController.createArrayOfQuestions(folder, reqType, _isRequests);
      return;
    }
  } else {
    let requestArray = [];
    let requestObject = {};
    requestObject["type"] = "interrogatories";
    requestObject["requests"] = rogs;
    requestArray.push(requestObject);
    const docId = folder;
    const reqType = "interrogatories"; //determinedDocType var value is lost by here not sure why but this hack should fix
    const saveDirectory = path.join(
      __dirname,
      "..",
      "Documents",
      "Requests",
      "interrogatories",
      `${folder}`
    );

    fs.mkdir(`${saveDirectory}`, function (err) {
      if (err) {
        console.log("makeDir utilities error creating directory: " + err);
      }
    });

    const fileSuffix = "-jbk-parsedRequests.json";
    const data = JSON.stringify(requestArray);
    console.log(
      "************************************************************** parseRogs updating DB"
    );
    updateDB(docId, reqType);
    console.log(
      " `${saveDirectory}/${docId}${fileSuffix}`",
      `${saveDirectory}/${folder}${fileSuffix}`
    );
    fs.writeFileSync(
      `${saveDirectory}/${folder}${fileSuffix}`,
      data,
      function (err) {
        if (err) {
          return console.log("Error in parseRogs writeFile:", err);
        }
      }
    );
    // Send it straight to LLM
    const isRequests = false;
    modelController.arrayGenAnswers(docId, reqType, isRequests);
  }
}

/*******************************************************************************
 *
 *  Create a directory
 *
 *******************************************************************************/

async function makeDir(folder, determinedDocType) {
  let dir;
  if (determinedDocType === "interrogatories") {
    dir = path.join(
      __dirname,
      "..",
      "Documents",
      "Requests",
      "interrogatories",
      `${folder}`
    );
  } else if (determinedDocType === "production") {
    dir = path.join(
      __dirname,
      "..",
      "Documents",
      "Requests",
      "production",
      `${folder}`
    );
  } else if (determinedDocType === "admissions") {
    dir = path.join(
      __dirname,
      "..",
      "Documents",
      "Requests",
      "admissions",
      `${folder}`
    );
  } else if (determinedDocType === "combined-numbered") {
    dir = path.join(
      __dirname,
      "..",
      "Documents",
      "Requests",
      "combnined-numbered",
      `${folder}`
    );
  } else {
    dir = `../Documents/Requests/Fallback/${folder}`;
  }
  fs.mkdir(dir, function (err) {
    if (err) {
      console.log("docParser makeDir error.  Error Creating Directory: " + err);
    }
  });
}

/*******************************************************************************
 *
 *  Write result to a file
 *
 *******************************************************************************/

function saveParsedRogs(rogs, folder, determinedDocType) {
  let dir;
  const fdirup = path.join(__dirname, "..", "Documents", "Requests");

  const data2 = JSON.stringify(rogs);
  if (determinedDocType === "interrogatories") {
    dir = `${fdirup}/interrogatories/${folder}/`;
  } else if (determinedDocType === "production") {
    dir = `${fdirup}/production/${folder}/`;
  } else if (determinedDocType === "admissions") {
    dir = `${fdirup}/admissions/${folder}/`;
  } else if (determinedDocType === "combined-numbered") {
    dir = `${fdirup}/combined-numbered/${folder}/`;
  }

  try {
    if (folder) {
      updateDB(folder, determinedDocType);
    }
    fs.writeFile(
      dir + `${folder}-jbk-parsedRequests.json`,
      data2,
      function (err) {
        if (err) {
          return console.log("Error writing in saveParsedRogs", err);
        }
      }
    );
  } catch (err) {
    console.log("docParser saveParsedRogs error. Error writing file:", err);
  }
}
/*
const reqType = "admissions";
const docId = "73cf6d0d-15cd-4d12-9edc-00bfa8de8ebb";
const isRequests = true;

modelController.testSaveFunction(docId, reqType, isRequests);
*/
module.exports = {
  readDir,
  makeDir,
  saveParsedRogs,
};
