const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs');
const path = require('path');

const PizZip = require('pizzip');
const vCard = require('vcf');
const Docxtemplater = require('docxtemplater');
const ExcelJS = require('exceljs');
const ics = require('ics');
const dayjs = require('dayjs');
const advancedFormat = require('dayjs/plugin/advancedFormat');
const numberToWords = require('number-to-words');

const { fieldToCellMap } = require('./constants');

// Define directoryPath for Client Folder Location

// Define possible directory paths
const linuxPath = '/mnt/DropBox/clients';
const windowsPath = 'D:\\Bklistservinfo Dropbox\\Ryan Callahan\\clients';

// Function to check if a directory exists and is accessible
function isDirectoryAccessible(path) {
    try {
        if (!fs.existsSync(path)) {
            console.log(`Path does not exist: ${path}`);
            return false;
        }
        if (!fs.statSync(path).isDirectory()) {
            console.log(`Path is not a directory: ${path}`);
            return false;
        }
        fs.accessSync(path, fs.constants.W_OK);
        return true;
    } catch (err) {
        console.log(`No access to path: ${path}, Error: ${err.message}`);
        return false;
    }
}

// Use the Linux path if it's accessible; otherwise, fallback to Windows path
const directoryPath = isDirectoryAccessible(linuxPath) ? linuxPath : windowsPath;

console.log(`Using directory path: ${directoryPath}`);




dayjs.extend(advancedFormat);

let today = dayjs();
console.log(today.format('MMMM Do, YYYY')); // Output: July 14th, 2023

const app = express();

// Default to root for local dev — set BASE_PATH to "/" locally or to "/your-base" behind Apache
const BASE_PATH = process.env.BASE_PATH || '/';

const router = express.Router();

// Apply JSON/body-parser and static middleware to the router so routes are mounted under BASE_PATH
router.use(bodyParser.json());
router.use(express.json()); // Middleware to parse JSON bodies
router.use(express.static(path.join(__dirname, 'public')));



function generateDocument(data, documentPath) {
  let content = fs.readFileSync(
    path.resolve(__dirname, documentPath),
    'binary'
  );
  let zip = new PizZip(content);
  let doc = new Docxtemplater();
  doc.loadZip(zip);
  doc.setData(data);

  try {
    doc.render();
  } catch (error) {
    var e = {
      message: error.message,
      name: error.name,
      stack: error.stack,
      properties: error.properties,
    };
    console.log(JSON.stringify({ error: e }));
    throw error;
  }
  return doc.getZip().generate({ type: 'nodebuffer' });
}


async function generateClientFolder(data) {
  const folderPath = directoryPath; // Path for the folder

  // Check if directoryPath exists
  if (!fs.existsSync(folderPath)) {
    console.error(`Error: The directory path ${folderPath} does not exist.`);
    return; // Exit the function without crashing the code
  }

  const subFolderPath = path.join(folderPath, `${data.clientLastName}, ${data.clientFirstName}`); // Path for the subfolder
  const subfolderCasePath = path.join(subFolderPath, `${data.caseNumber}_${data.casePlaintiffFileName}`); // Path for the case subfolder

  // Check if the main "client" folder exists
  if (!fs.existsSync(folderPath)) {
    // If it doesn't exist, create the "client" folder
    fs.mkdirSync(folderPath, { recursive: true });
    console.log(`Folder created at: ${folderPath}`);
  }

  // Check if the subfolder for the client exists
  if (!fs.existsSync(subFolderPath)) {
    // If it doesn't exist, create the subfolder
    fs.mkdirSync(subFolderPath, { recursive: true });
    console.log(`Subfolder created at: ${subFolderPath}`);
  } else {
    console.log(`Subfolder already exists at: ${subFolderPath}`);
  }

  // Check if the case documents subfolder exists
  if (!fs.existsSync(subfolderCasePath)) {
    // If it doesn't exist, create the case documents subfolder
    fs.mkdirSync(subfolderCasePath, { recursive: true });
    console.log(`Case documents subfolder created at: ${subfolderCasePath}`);
  } else {
    console.log(`Case documents subfolder already exists at: ${subfolderCasePath}`);
  }

  /* Dynamically import the 'open' module and open the subfolder
  try {
    const open = (await import('open')).default;
    await open(subFolderPath);
    console.log(`Opened ${subFolderPath}`);
  } catch (err) {
    console.error(`Failed to open ${subFolderPath}:`, err);
  }
  */
}


function createVCard(data) {
  let card = new vCard();

  // Set the fields in the vCard
  card.set(
    'fn',
    `${data.clientFirstName} ${data.clientMiddleName} ${data.clientLastName} ${data.clientNameSuffix}`
  );
  card.set(
    'n',
    `${data.clientLastName};${data.clientFirstName};${data.clientMiddleName};;${data.clientNameSuffix}`
  );
  card.set('email', data.email);
  card.add('tel', data.homePhone, { type: 'home' });
  card.add('tel', data.cellPhone, { type: 'cell' });
  card.add(
    'adr',
    `;;${data.homeAddress};${data.homeCity};${data.homeState};${data.homeZip}`,
    { type: 'home' }
  ); // Set the 'adr' field with a type of 'home'
  card.set('bday', data.dob);
  card.set(
    'note',
    `Representation on ${data.casePlaintiff} v. ${data.caseDefendant}, ${data.caseNumber}`
  );
  card.set('org', `Clients - ${data.homeState}`);

  return card.toString();
}



async function generateExcel(data) {
  const workbook = new ExcelJS.Workbook();
  await workbook.xlsx.readFile(path.resolve(__dirname, 'template.xlsx'));
  const worksheet = workbook.getWorksheet(1);
  for (let field in fieldToCellMap) {
    if (fieldToCellMap.hasOwnProperty(field) && data.hasOwnProperty(field)) {
      worksheet.getCell(fieldToCellMap[field]).value = data[field];
    }
  }
  return await workbook.xlsx.writeBuffer();
}

router.post('/generate-excel', async (req, res) => {
  const data = req.body;
  let buf = await generateExcel(data);
  let filename = `${data.clientLastName}-${data.clientFirstName}_${data.caseNumber}_Data.xlsx`;
  res.setHeader(
    'Content-Type',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  );
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});



router.post('/generate-ics', (req, res) => {
  const data = req.body;
  const eventName = `${data.casePlaintiff} v. ${data.caseDefendant}`;
  const location = `${data.caseCounty} County ${data.caseDesignation} Court, Div ${data.caseDivisionNumber}`;
  const startDateArray = dayjs(data.caseAnswerDate)
    .format('YYYY-M-D-H-m')
    .split('-')
    .map(Number);
  const endDateArray = dayjs(data.caseAnswerDate)
    .add(30, 'minute')
    .format('YYYY-M-D-H-m')
    .split('-')
    .map(Number);

  // Create the HTML table
  const description = `Case No: ${data.caseNumber}\t  Client Name: ${data.clientFirstName} ${data.clientLastName}
    Appearance Information: Judge: ${data.caseDivisionJudge};  Suit Amount: $${data.caseSuitAmount};
    Case Information: First Court Date: ${data.caseAnswerDate};  Opposing Counsel: ${data.caseOpposingCounsel};  Suit Theory: ${data.caseSuitTheory}`;

  const { error, value } = ics.createEvent({
    start: startDateArray,
    end: endDateArray,
    title: eventName,
    description: description, // Add the description here
    location: location,
  });

  if (error) {
    console.log(error);
    return res.status(500).send({ error });
  }

  let filename = `${eventName}.ics`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(value);
});

router.post('/generate-MOdisco-ics', (req, res) => {
  const data = req.body;

  // Get the Discovery CoS Date from the request body
  const discoCosDate = data.discoCosDate;

  // Parse the Discovery CoS Date and add 30 days to get the discovery response date
  const discoveryResponseDate = dayjs(discoCosDate).add(30, 'days');
  const startDateArray = discoveryResponseDate
    .format('YYYY-M-D')
    .split('-')
    .map(Number);
  const endDateArray = discoveryResponseDate
    .add(1, 'day')
    .format('YYYY-M-D')
    .split('-')
    .map(Number);

  // Set the event title, description, and location
  const eventName = `DISCO due on ${data.casePlaintiff} v. ${data.caseDefendant}, ${data.caseNumber}`;
  const description = `CoS Date: ${discoCosDate}`; // Add the CoD Date to the description
  const location = `${data.caseCounty} County ${data.caseDesignation} Court, Div ${data.caseDivisionNumber}`;

  const { error, value } = ics.createEvent({
    start: startDateArray,
    end: endDateArray,
    title: eventName,
    description: description,
    location: location,
  });

  if (error) {
    console.log(error);
    return res.status(500).send({ error });
  }

  let filename = `${eventName}.ics`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(value);
});

router.post('/generate-KSdisco-ics', (req, res) => {
  const data = req.body;

  // Get the Discovery CoS Date from the request body
  const discoCosDate = data.discoCosDate;

  // Parse the Discovery CoS Date and add 30 days to get the discovery response date
  const discoveryResponseDate = dayjs(discoCosDate).add(14, 'days');
  const startDateArray = discoveryResponseDate
    .format('YYYY-M-D')
    .split('-')
    .map(Number);
  const endDateArray = discoveryResponseDate
    .add(1, 'day')
    .format('YYYY-M-D')
    .split('-')
    .map(Number);

  // Set the event title, description, and location
  const eventName = `DISCO due on ${data.casePlaintiff} v. ${data.caseDefendant}, ${data.caseNumber}`;
  const description = `CoS Date: ${discoCosDate}`; // Add the CoD Date to the description
  const location = `${data.caseCounty} County ${data.caseDesignation} Court, Div ${data.caseDivisionNumber}`;

  const { error, value } = ics.createEvent({
    start: startDateArray,
    end: endDateArray,
    title: eventName,
    description: description,
    location: location,
  });

  if (error) {
    console.log(error);
    return res.status(500).send({ error });
  }

  let filename = `${eventName}.ics`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(value);
});

router.post('/generate-vCard', (req, res) => {
  const data = req.body; // This is your form data
  let vCardString = createVCard(data);

  let filename = `${data.caseNumber}-contact.vcf`; // Modify this line to use your desired filename
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.type('text/vcard');
  res.send(vCardString);
});

router.post('/generate-reminder-ics', (req, res) => {
  const data = req.body;

  // Get the current date
  const today = dayjs();

  // Add 45 days to the current date
  const futureDate = today.add(45, 'days');
  const startDateArray = futureDate
    .format('YYYY-M-D')
    .split('-')
    .map(Number);
  const endDateArray = futureDate
    .add(1, 'day')
    .format('YYYY-M-D')
    .split('-')
    .map(Number);

  // Set the event title, description, and location
  const todayDate = dayjs().format('MM/DD/YYYY');
  const eventName = `REMINDER - ${data.clientFirstName} ${data.clientLastName} - Check Credit Dispute Reporting`;
  let description = `FDCPA Disputes were mailed on ${todayDate} to:\n`;

  for (let i = 1; i <= 9; i++) {
    let name = data[`debtCollector${i}Name`];
    let creditor = data[`debtCollector${i}Creditor`];
    let account = data[`debtCollector${i}Account`];
    let amount = data[`debtCollector${i}Amount`];

    if (name) {
      description += `- ${name} \n \tregarding a ${creditor} account (Acc. No. ${account}) for $${amount},\n`;
    }
  }

  // Remove the last comma and newline
  description = description.trim().slice(0, -1);


  const { error, value } = ics.createEvent({
    start: startDateArray,
    end: endDateArray,
    title: eventName,
    description: description,
  });

  if (error) {
    console.log(error);
    return res.status(500).send({ error });
  }

  let filename = `${eventName}.ics`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(value);
});

router.post('/generate-vCard', (req, res) => {
  const data = req.body; // This is your form data
  let vCardString = createVCard(data);

  let filename = `${data.caseNumber}-contact.vcf`; // Modify this line to use your desired filename
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.type('text/vcard');
  res.send(vCardString);
});



router.post('/generate-ics-body', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'isc-body.docx');
  let filename = `${data.caseNumber}-ics-body.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-retainer', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'retainer.docx');
  let filename = `${data.clientLastName}-${data.clientFirstName}_${data.caseNumber}_Representation-and-Fee-Agreement.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-eoa', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'entry.docx');
  let filename = `${data.caseNumber}_EoA.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-notes', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'notes.docx');
  let filename = `${data.clientLastName}-${data.clientFirstName} - Intake and Notes.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-spreadsheet', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'spreadsheets.docx');
  let filename = `${data.clientLastName}-${data.clientFirstName}_Spreadsheets.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-ADs', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'defenses.docx');
  let filename = `${data.caseNumber}_Affirmative-Defenses.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-closeout', (req, res) => {
  const data = req.body;

  let buf = generateDocument(data, 'closeout.docx');
  let filename = `${data.caseNumber}_${data.clientLastName}_Closeout-Letter.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-closeout-with-costs', (req, res) => {
  const data = req.body;

  let buf = generateDocument(data, 'closeout_CJ_with-interest-costs.docx');
  let filename = `${data.caseNumber}_${data.clientLastName}_Closeout.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-waiver', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'waiver.docx');
  let filename = `${data.caseNumber}_Service-Waiver.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-pleading', (req, res) => {
  const data = req.body;
  let templateName = data.templateName; // This should be sent from the client side
  if (!templateName) {
    res.status(400).send('Template name is required');
    return;
  }
  let templatePath = path.join(__dirname, 'Pleadings', `${templateName}.docx`);
  let buf = generateDocument(data, templatePath);
  let filename = `${data.caseNumber}_Pleading.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-disco', (req, res) => {
  const data = req.body;
  let templateName = data.templateName; // This should be sent from the client side
  if (!templateName) {
    res.status(400).send('Template name is required');
    return;
  }
  let templatePath = path.join(__dirname, 'Discovery', `${templateName}.docx`);
  let buf = generateDocument(data, templatePath);
  let filename = `${data.caseNumber}_Disco-Responses.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-letter', (req, res) => {
  const data = req.body;
  let templateName = data.templateName; // This should be sent from the client side
  if (!templateName) {
    res.status(400).send('Template name is required');
    return;
  }
  let templatePath = path.join(__dirname, 'Letters', `${templateName}.docx`);
  let buf = generateDocument(data, templatePath);
  let filename = `${data.clientLastName}-${data.clientFirstName}_${data.caseNumber}_Letter.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-Canned-Emails', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'Canned-Emails.docx');
  let filename = `${data.caseNumber}_Canned-Emails.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-Dispute-Letter', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'letter.docx');
  let date = dayjs().format('YYYY-MM-DD');
  let filename = `${data.clientLastName}_FDCPA-Disputes_${date}.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-Dispute-Envelope', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'dispute-envelopes.docx');
  let date = dayjs().format('YYYY-MM-DD');
  let filename = `${data.clientLastName}_FDCPA-Disputes_${date}_Envelopes.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-Dispute-Cert', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'cert-mailing.docx');
  let date = dayjs().format('YYYY-MM-DD');
  let filename = `${data.clientLastName}_FDCPA-Disputes_${date}_Mail-Cert.docx`;
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-client-folder', (req, res) => {
  const data = req.body;
  let buf = generateClientFolder(data);

  res.send(buf);
});

router.post('/generate-credit-auth', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'authorization-disclosure.docx');
  let filename = `${data.clientLastName}-${data.clientFirstName}_Credit-Authorization.docx`;
 res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

router.post('/generate-credit-auth-no-payment', (req, res) => {
  const data = req.body;
  let buf = generateDocument(data, 'authorization-disclosure-no-payment.docx');
  let filename = `${data.clientLastName}-${data.clientFirstName}_Credit-Authorization-No-Payment.docx`;
  
  res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
  res.send(buf);
});

// Mount router under BASE_PATH
if (BASE_PATH === '/') {
  app.use('/', router); // local dev
} else {
  app.use(BASE_PATH, router); // behind Apache or with a base path
}

const PORT = process.env.PORT || 3001;
app.listen(PORT, '0.0.0.0', () => console.log(`Server is running and accessible on ${BASE_PATH} at port ${PORT}`));
