import {
  fields,
  stateToPostalCode,
  specificNames,
  specificTwoLetters,
  postalCode,
  fieldToCellMap,
  fieldToCellMapOld,
} from './constants.js';

import { judgeInfo } from './judgeInformation.js';
import { casePlaintiffInfo } from './casePlaintiffInfo.js';

import {
  caseOpposingCounselInfo,
  caseFilingAttorneyInfo,
} from './opposingCounselInfo.js';

import { generateLink } from './linkGenerator.js';

function toOrdinal(n) {
  var s = ['th', 'st', 'nd', 'rd'],
    v = n % 100;
  return n + (s[(v - 20) % 10] || s[v] || s[0]);
}

let savedData = {};

function byId(id) {
  return document.getElementById(id);
}

function onClick(id, handler) {
  const el = byId(id);
  if (el) el.addEventListener('click', handler);
}

function onChange(id, handler) {
  const el = byId(id);
  if (el) el.addEventListener('change', handler);
}

function onInput(id, handler) {
  const el = byId(id);
  if (el) el.addEventListener('input', handler);
}

function onSubmit(id, handler) {
  const el = byId(id);
  if (el) el.addEventListener('submit', handler);
}

function getFirstByName(name) {
  const elements = document.getElementsByName(name);
  return elements && elements.length > 0 ? elements[0] : null;
}

function safeString(value) {
  return value == null ? '' : String(value);
}

function safeLastFour(value) {
  const str = safeString(value);
  return str ? str.slice(-4) : '';
}

function parseMoney(value) {
  const parsed = parseFloat(safeString(value).replace(/,/g, ''));
  return isNaN(parsed) ? 0 : parsed;
}

window.addEventListener('load', () => {
  let inputs = document.getElementsByTagName('input');
  for (let input of inputs) {
    if (savedData[input.id] && !savedData[input.id].includes('xlsx')) {
      input.value = savedData[input.id];
    }
    input.addEventListener('input', function () {
      savedData[this.id] = this.value;
    });
  }

  generateFields(0);
});

function generateFields(numCollectors) {
  let container = byId('collectorsContainer');
  if (!container) return;

  container.innerHTML = '';

  for (let i = 1; i <= 30; i++) {
    let div = document.createElement('div');
    div.id = 'collector' + i;
    div.style.display = i <= numCollectors ? 'block' : 'none';
    div.innerHTML = `
      <h3>Letter to Collector #${i}</h3>
      <div class="form-row">
        <div class="form-group">
          <label for="debtCollector${i}Name">Debt Collector ${i} Name:</label>
          <input type="text" id="debtCollector${i}Name" name="debtCollector${i}Name" onblur="titleCase(this)">
        </div>
        <div class="form-group">
          <label for="debtCollector${i}AddressLine1">Debt Collector ${i} Address L1:</label>
          <input type="text" id="debtCollector${i}AddressLine1" name="debtCollector${i}AddressLine1" onblur="titleCase(this)">
        </div>
        <div class="form-group">
          <label for="debtCollector${i}AddressLine2">Debt Collector ${i} Address L2:</label>
          <input type="text" id="debtCollector${i}AddressLine2" name="debtCollector${i}AddressLine2" onblur="titleCase(this)">
        </div>
      </div>
      <div class="form-row">
        <div class="form-group">
          <label for="debtCollector${i}Creditor">Debt Collector ${i} Creditor:</label>
          <input type="text" id="debtCollector${i}Creditor" name="debtCollector${i}Creditor" onblur="titleCase(this)">
        </div>
        <div class="form-group">
          <label for="debtCollector${i}Account">Debt Collector ${i} Account #:</label>
          <input type="text" id="debtCollector${i}Account" name="debtCollector${i}Account">
        </div>
        <div class="form-group">
          <label for="debtCollector${i}Amount">Debt Collector ${i} Amount:</label>
          <input type="text" id="debtCollector${i}Amount" name="debtCollector${i}Amount" onblur="formatCurrency(this)">
        </div>
      </div>
    `;

    let inputs = div.querySelectorAll('input');
    inputs.forEach((input) => {
      if (savedData[input.id]) {
        input.value = savedData[input.id];
      }

      input.addEventListener('input', function () {
        savedData[this.id] = this.value;
        localStorage.setItem('collectorData', JSON.stringify(savedData));
      });
    });

    container.appendChild(div);
  }
}
window.generateFields = generateFields;

const numCollectorsEl = byId('numCollectors');
if (numCollectorsEl) {
  numCollectorsEl.onchange = function () {
    const numCollectors = this.value;
    for (let i = 1; i <= 30; i++) {
      const div = byId('collector' + i);
      if (div) {
        div.style.display = i <= numCollectors ? 'block' : 'none';
      }
    }
  };
}

onClick('generateClientFolderLinkBtn', function () {
  let container = byId('clientFolderLinkContainer');
  if (!container) return;

  const clientFirstName = safeString(byId('clientFirstName')?.value);
  const clientLastName = safeString(byId('clientLastName')?.value);
  const folderPath = `file:///D:/Bklistservinfo Dropbox/Ryan Callahan/clients/${clientLastName}, ${clientFirstName}`;
  container.innerHTML = `<a href="${folderPath}">Open Client Folder</a>`;
});

onClick('generateCaseLinkBtn', function () {
  let container = byId('caseLinkContainer');
  if (!container) return;

  const caseNumberInput = safeString(byId('caseNumber')?.value);
  const link = generateLink(caseNumberInput);

  if (link) {
    container.innerHTML = `<a href="${link}">Open Case</a>`;
  }
});

async function sendFormData(path, data, templateName) {
  data.templateName = templateName;

  const normalizedPaths = [];
  const seen = new Set();

  const addPath = (p) => {
    if (!p || seen.has(p)) return;
    seen.add(p);
    normalizedPaths.push(p);
  };

  addPath(path);

  if (path.startsWith('/')) {
    addPath(path.slice(1));
  } else {
    addPath(`/${path}`);
  }

  let lastError = null;

  for (const candidate of normalizedPaths) {
    try {
      const response = await fetch(candidate, {
        method: 'POST',
        body: JSON.stringify(data),
        headers: {
          'Content-Type': 'application/json',
        },
      });

      if (!response.ok) {
        lastError = new Error(`Request failed for ${candidate}: ${response.status}`);
        continue;
      }

      const contentDisposition = response.headers.get('Content-Disposition');
      let filename = 'output.docx';

      if (contentDisposition) {
        const filenameMatch = contentDisposition.match(/filename="(.+)"/);
        if (filenameMatch && filenameMatch.length === 2) {
          filename = filenameMatch[1];
        }
      }

      const blob = await response.blob();
      const downloadUrl = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = downloadUrl;
      a.download = filename;
      document.body.appendChild(a);
      a.click();

      setTimeout(() => {
        document.body.removeChild(a);
        URL.revokeObjectURL(downloadUrl);
      }, 0);

      return;
    } catch (error) {
      lastError = error;
    }
  }

  console.error('sendFormData failed:', lastError);
  alert('Unable to reach the document generation route.');
}

function getFormData() {
  let data = {};
  fields.forEach((field) => {
    data[field] = byId(field) ? byId(field).value : null;
  });

  data.today = dayjs().format('MMMM Do, YYYY');
  data.currentDate = dayjs().format('YYYY-MM-DD');
  data['currentDateMM-DD-YYYY'] = dayjs().format('MM-DD-YYYY');

  if (data.dob) {
    if (/^\d{4}$/.test(data.dob)) {
      data.dob = data.dob;
    } else {
      data.dob = dayjs(data.dob).format('MM/DD/YYYY');
    }
  }

  let installmentDate = dayjs(data.installmentDate);
  data.installmentDate0 = installmentDate.format('MM/DD/YYYY');

  for (let i = 1; i < 10; i++) {
    installmentDate = installmentDate.add(1, 'month');
    data[`installmentDate${i}`] = installmentDate.format('MM/DD/YYYY');
  }

  if (data.caseAnswerDate) {
    const [datePart = '', timePart = ''] = data.caseAnswerDate.split(';');
    const trimmedDatePart = datePart.trim();
    const trimmedTimePart = timePart.trim();

    data['caseAnswerDateYYYY-MM-DD'] = dayjs(trimmedDatePart, 'MM/DD/YYYY').format('YYYY-MM-DD');
    data.caseAnswerDateTime = trimmedTimePart;
    data.caseAnswerDateOnly = trimmedDatePart;
  }

  let judgeLastName = safeString(data.caseDivisionJudge).split(' ').pop();

  data.caseAppearanceInfo =
    judgeInfo[judgeLastName]
      ? `Division: ${judgeInfo[judgeLastName].division}; ${judgeInfo[judgeLastName].modality}`
      : 'Modality: In-person; Access Code: N/A; Phone # / Link: N/A';

  data.caseDivisionLocation =
    judgeInfo[judgeLastName] && judgeInfo[judgeLastName].location
      ? judgeInfo[judgeLastName].location
      : ' ';

  let caseOpposingCounsel = safeString(getFirstByName('caseOpposingCounsel')?.value);

  data.caseOCAddressLine1 =
    caseOpposingCounselInfo[caseOpposingCounsel]
      ? caseOpposingCounselInfo[caseOpposingCounsel].caseOCAddressLine1
      : 'Address Line 1 Not Found';
  data.caseOCAddressLine2 =
    caseOpposingCounselInfo[caseOpposingCounsel]
      ? caseOpposingCounselInfo[caseOpposingCounsel].caseOCAddressLine2
      : 'Address Line 2 Not Found';
  data.caseOCPhone =
    caseOpposingCounselInfo[caseOpposingCounsel]
      ? caseOpposingCounselInfo[caseOpposingCounsel].caseOCPhone
      : '111-111-1111';
  data.caseOCFax =
    caseOpposingCounselInfo[caseOpposingCounsel]
      ? caseOpposingCounselInfo[caseOpposingCounsel].caseOCFax
      : '111-111-1112';
  data.caseOCEmail =
    caseOpposingCounselInfo[caseOpposingCounsel]
      ? caseOpposingCounselInfo[caseOpposingCounsel].caseOCEmail
      : 'email@domain.com';
  data.paymentOptions1 =
    caseOpposingCounselInfo[caseOpposingCounsel] && caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions1
      ? caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions1
      : 'Payment Options Not Found';
  data.paymentOptions2 =
    caseOpposingCounselInfo[caseOpposingCounsel] && caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions2
      ? caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions2
      : ' ';
  data.paymentOptions3 =
    caseOpposingCounselInfo[caseOpposingCounsel] && caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions3
      ? caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions3
      : ' ';
  data.paymentOptions4 =
    caseOpposingCounselInfo[caseOpposingCounsel] && caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions4
      ? caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions4
      : ' ';
  data.paymentOptions5 =
    caseOpposingCounselInfo[caseOpposingCounsel] && caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions5
      ? caseOpposingCounselInfo[caseOpposingCounsel].paymentOptions5
      : ' ';

  const casePlaintiffEl = byId('casePlaintiff');
  const casePlaintiffValue = safeString(casePlaintiffEl?.value);

  if (caseOpposingCounselInfo && caseOpposingCounselInfo[caseOpposingCounsel]) {
    if (caseOpposingCounselInfo[caseOpposingCounsel].settlementPayee === 'casePlaintiff') {
      data.settlementPayee = casePlaintiffValue;
    } else {
      data.settlementPayee = caseOpposingCounselInfo[caseOpposingCounsel].settlementPayee;
    }
  } else {
    data.settlementPayee = 'Payee not found';
  }

  let caseFilingAttorney = safeString(getFirstByName('caseFilingAttorney')?.value);

  data.caseAttyFirstName =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttyFirstName
      : 'First Name Not Found';
  data.caseAttyLastName =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttyLastName
      : 'Last Name Not Found';
  data.caseAttyAddressLine1 =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttyAddressLine1
      : 'Address Line 1 Not Found';
  data.caseAttyAddressLine2 =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttyAddressLine2
      : 'Address Line 2 Not Found';
  data.caseAttyPhone =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttyPhone
      : '111-111-1111';
  data.caseAttyFax =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttyFax
      : '111-111-1112';
  data.caseAttyEmail =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttyEmail
      : 'email@domain.com';
  data.caseAttybarMO =
    caseFilingAttorneyInfo[caseFilingAttorney]
      ? caseFilingAttorneyInfo[caseFilingAttorney].caseAttybarMO
      : '######';

  function formatDateString(dateString) {
    let date = new Date(dateString);

    if (!isNaN(date)) {
      let day = date.getDate();
      let dayOrdinal = toOrdinal(day);

      return `${date.toLocaleDateString('en-US', {
        month: 'long',
      })} ${dayOrdinal}, ${date.getFullYear()}`;
    } else {
      console.error('Invalid Date');
      return 'Invalid Date';
    }
  }

  data.caseDispositionDateString = formatDateString(data.caseDispositionDate);
  data.caseFilingDateString = formatDateString(data.caseFilingDate);
  data.caseAnswerDateString = formatDateString(data.caseAnswerDateOnly);
  data.caseAnswerFiledDateString = formatDateString(data.caseAnswerFiledDate);
  data.discoCosDateString = formatDateString(data.discoCosDate);
  data.discoResponseCosDateString = formatDateString(data.discoResponseCosDate);

  let caseSuitAmount = parseMoney(data.caseSuitAmount);
  let settlementAmount = parseMoney(data.settlementAmount);
  let waivedAmount = caseSuitAmount - settlementAmount;

  let settlementOfferPercentExpected = data.settlementOfferPercentExpected ? parseFloat(data.settlementOfferPercentExpected) : 0;
  let settlementOfferPercentCurrent = data.settlementOfferPercentCurrent ? parseFloat(data.settlementOfferPercentCurrent) : 0;

  let settlementOfferExpected = (caseSuitAmount * (settlementOfferPercentExpected / 100)).toFixed(2);
  data.settlementOfferExpected = settlementOfferExpected;

  let settlementOfferCurrent = (caseSuitAmount * (settlementOfferPercentCurrent / 100)).toFixed(2);
  data.settlementOfferCurrent = settlementOfferCurrent;

  let settlementOfferAmount = safeString(byId('settlementOfferAmount')?.value);
  let settlementOffer = parseMoney(settlementOfferAmount).toFixed(2);
  settlementOffer = parseFloat(settlementOffer).toLocaleString('en-US', { minimumFractionDigits: 2 });

  data.settlementOffer = settlementOffer;

  data.waivedAmount = waivedAmount.toLocaleString('en-US', {
    style: 'currency',
    currency: 'USD',
  });

  let settlementFirstPaymentDate = new Date(data.settlementFirstPaymentDate);

  data.settlementFirstPaymentDateString = settlementFirstPaymentDate.toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });

  let day = settlementFirstPaymentDate.getDate();
  data.settlementFirstPaymentDayString = toOrdinal(day);

  let settlementInstallmentAmount = parseMoney(data.settlementInstallmentAmount);

  data.settlementInstallmentAmountString = isNaN(settlementInstallmentAmount)
    ? ''
    : settlementInstallmentAmount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });

  if (!isNaN(settlementInstallmentAmount)) {
    const dollars = Math.floor(settlementInstallmentAmount);
    const cents = Math.round((settlementInstallmentAmount - dollars) * 100);
    const dollarsText = numberToWords.toWords(dollars);
    const centsText = numberToWords.toWords(cents);
    data.settlementInstallmentAmountWords =
      `${dollarsText.charAt(0).toUpperCase() + dollarsText.slice(1)} Dollar${dollars !== 1 ? 's' : ''} and ${centsText.charAt(0).toUpperCase() + centsText.slice(1)} Cent${cents !== 1 ? 's' : ''}`;
  } else {
    data.settlementInstallmentAmountWords = '';
  }

  let settlementCheckDate = new Date(settlementFirstPaymentDate);
  settlementCheckDate.setDate(settlementFirstPaymentDate.getDate() - 10);

  data.settlementCheckDate = settlementCheckDate.toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });

  function adjustAndFormatDate(date) {
    let day = date.getDate();
    let month = date.getMonth();
    let year = date.getFullYear();

    let lastDayOfMonth = new Date(year, month + 1, 0).getDate();
    if (day > lastDayOfMonth) {
      day = lastDayOfMonth;
    }

    let adjustedDate = new Date(year, month, day);

    let formattedMonth = (adjustedDate.getMonth() + 1).toString().padStart(2, '0');
    let formattedDay = adjustedDate.getDate().toString().padStart(2, '0');
    let formattedYear = adjustedDate.getFullYear();
    return `${formattedMonth}/${formattedDay}/${formattedYear}`;
  }

  data.settlementPaymentDate01 = settlementFirstPaymentDate.toLocaleDateString('en-US', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
  });

  for (let i = 1; i < 60; i++) {
    let paymentDate = new Date(settlementFirstPaymentDate);
    paymentDate.setMonth(paymentDate.getMonth() + i);

    let lastDayOfMonth = new Date(paymentDate.getFullYear(), paymentDate.getMonth() + 1, 0).getDate();
    if (settlementFirstPaymentDate.getDate() > lastDayOfMonth) {
      paymentDate.setDate(lastDayOfMonth);
    }

    let formattedDate = adjustAndFormatDate(paymentDate);
    data[`settlementPaymentDate${(i + 1).toString().padStart(2, '0')}`] = formattedDate;
  }

  for (let i = 1; i < 60; i++) {
    let paymentDateKey = `settlementPaymentDate${(i + 1).toString().padStart(2, '0')}`;
    let paymentDate = new Date(data[paymentDateKey]);
    if (paymentDate.getDate() !== settlementFirstPaymentDate.getDate()) {
      paymentDate.setMonth(paymentDate.getMonth() - 1);
      paymentDate.setDate(new Date(paymentDate.getFullYear(), paymentDate.getMonth() + 1, 0).getDate());
      data[paymentDateKey] = adjustAndFormatDate(paymentDate);
    }
  }

  let settlementInstallmentNo = parseInt(data.settlementInstallmentNo, 10);
  let settlementInterestRate = parseFloat(data.settlementInterestRate) || 0.00000000000000000001;

  settlementAmount = parseMoney(data.settlementAmount);
  let settlementCaseCosts = parseMoney(data.settlementCaseCosts);

  let monthlyInterestRate = settlementInterestRate / 100 / 12;

  let settlementPaymentAmounts = [];
  let settlementRemainingBalances = [];
  let cumulativeInterest = 0;

  for (let i = 0; i < settlementInstallmentNo; i++) {
    let interestPayment = settlementAmount * monthlyInterestRate;
    let principalPayment = settlementInstallmentAmount - interestPayment;

    if (settlementAmount < principalPayment) {
      principalPayment = settlementAmount;
      settlementInstallmentAmount = principalPayment + interestPayment + settlementCaseCosts;
    }

    settlementAmount -= principalPayment;

    settlementPaymentAmounts.push(settlementInstallmentAmount.toFixed(2));
    settlementRemainingBalances.push(settlementAmount.toFixed(2));
    cumulativeInterest += interestPayment;

    if (settlementAmount <= 0) {
      break;
    }
  }

  if (settlementAmount > 0) {
    let finalInterestPayment = settlementAmount * monthlyInterestRate;
    let finalPayment = settlementAmount + finalInterestPayment + settlementCaseCosts;
    settlementPaymentAmounts.push(finalPayment.toFixed(2));
    settlementRemainingBalances.push('0.00');
    cumulativeInterest += finalInterestPayment;
  }

  for (let i = 0; i < 60; i++) {
    data[`settlementPaymentAmount${(i + 1).toString().padStart(2, '0')}`] = settlementPaymentAmounts[i] || '0.00';
    data[`settlementRemaingBalance${(i + 1).toString().padStart(2, '0')}`] = settlementRemainingBalances[i] || '0.00';
  }

  data.settlementTotalInterest = cumulativeInterest.toFixed(2);

  data.remainingAmount = parseFloat(settlementAmount.toFixed(2)).toLocaleString('en-US', {
    style: 'currency',
    currency: 'USD',
  });

  data.SSNLastFour = safeLastFour(data.SSN);
  data.SSN2LastFour = safeLastFour(data.client2SSN);
  data.caseAccLastFour = safeLastFour(data.caseAccountNumber);
  data.debtCollector1AccLastFour = safeLastFour(data.debtCollector1Account);
  data.debtCollector2AccLastFour = safeLastFour(data.debtCollector2Account);
  data.debtCollector3AccLastFour = safeLastFour(data.debtCollector3Account);
  data.debtCollector4AccLastFour = safeLastFour(data.debtCollector4Account);
  data.debtCollector5AccLastFour = safeLastFour(data.debtCollector5Account);
  data.debtCollector6AccLastFour = safeLastFour(data.debtCollector6Account);
  data.debtCollector7AccLastFour = safeLastFour(data.debtCollector7Account);
  data.debtCollector8AccLastFour = safeLastFour(data.debtCollector8Account);
  data.debtCollector9AccLastFour = safeLastFour(data.debtCollector9Account);
  data.debtCollector10AccLastFour = safeLastFour(data.debtCollector10Account);
  data.debtCollector11AccLastFour = safeLastFour(data.debtCollector11Account);
  data.debtCollector12AccLastFour = safeLastFour(data.debtCollector12Account);
  data.debtCollector13AccLastFour = safeLastFour(data.debtCollector13Account);
  data.debtCollector14AccLastFour = safeLastFour(data.debtCollector14Account);
  data.debtCollector15AccLastFour = safeLastFour(data.debtCollector15Account);
  data.debtCollector16AccLastFour = safeLastFour(data.debtCollector16Account);
  data.debtCollector17AccLastFour = safeLastFour(data.debtCollector17Account);
  data.debtCollector18AccLastFour = safeLastFour(data.debtCollector18Account);
  data.debtCollector19AccLastFour = safeLastFour(data.debtCollector19Account);
  data.debtCollector20AccLastFour = safeLastFour(data.debtCollector20Account);
  data.debtCollector21AccLastFour = safeLastFour(data.debtCollector21Account);
  data.debtCollector22AccLastFour = safeLastFour(data.debtCollector22Account);
  data.debtCollector23AccLastFour = safeLastFour(data.debtCollector23Account);
  data.debtCollector24AccLastFour = safeLastFour(data.debtCollector24Account);
  data.debtCollector25AccLastFour = safeLastFour(data.debtCollector25Account);
  data.debtCollector26AccLastFour = safeLastFour(data.debtCollector26Account);
  data.debtCollector27AccLastFour = safeLastFour(data.debtCollector27Account);
  data.debtCollector28AccLastFour = safeLastFour(data.debtCollector28Account);
  data.debtCollector29AccLastFour = safeLastFour(data.debtCollector29Account);
  data.debtCollector30AccLastFour = safeLastFour(data.debtCollector30Account);

  data.casePlaintiffFileName = safeString(data.casePlaintiff).replace(/ /g, '-').replace(/[,.]/g, '');

  return data;
}

let counselDataList = byId('counsel-list');
let counselNames = Object.keys(caseOpposingCounselInfo);

if (counselDataList) {
  for (let name of counselNames) {
    let option = document.createElement('option');
    option.value = name;
    counselDataList.appendChild(option);
  }
}

let filingAttorneyDataList = byId('attorney-list');
let filingAttorneyNames = Object.keys(caseFilingAttorneyInfo);

if (filingAttorneyDataList) {
  for (let name of filingAttorneyNames) {
    let option = document.createElement('option');
    option.value = name;
    filingAttorneyDataList.appendChild(option);
  }
}

let plaintiffDataList = byId('plaintiff-list');
let plaintiffNames = Object.keys(casePlaintiffInfo);

if (plaintiffDataList) {
  for (let name of plaintiffNames) {
    let option = document.createElement('option');
    option.value = name;
    plaintiffDataList.appendChild(option);
  }
}

let judgeDataList = byId('judge-list');
let judgeNames = Object.keys(judgeInfo);

if (judgeDataList) {
  for (let name of judgeNames) {
    let option = document.createElement('option');
    option.value = name;
    judgeDataList.appendChild(option);
  }
}

onInput('caseDivisionJudge', function () {
  let selectedJudge = this.value;
  if (judgeInfo[selectedJudge]) {
    if (byId('caseDivisionNumber')) byId('caseDivisionNumber').value = judgeInfo[selectedJudge].division;
    if (byId('caseDesignation')) byId('caseDesignation').value = judgeInfo[selectedJudge].designation;
    if (byId('caseCounty')) byId('caseCounty').value = judgeInfo[selectedJudge].county;
    if (byId('caseState')) byId('caseState').value = judgeInfo[selectedJudge].state;
    if (byId('caseDivisionDesignation')) byId('caseDivisionDesignation').value = judgeInfo[selectedJudge].divisionDesignation;
  } else {
    if (byId('caseDivisionNumber')) byId('caseDivisionNumber').value = '';
    if (byId('caseDesignation')) byId('caseDesignation').value = '';
    if (byId('caseCounty')) byId('caseCounty').value = '';
    if (byId('caseState')) byId('caseState').value = '';
    if (byId('caseDivisionDesignation')) byId('caseDivisionDesignation').value = '';
  }
});

onChange('excelFile', function (e) {
  readExcelFile(e);
});

onChange('excelFileOld', function (e) {
  readExcelFileOld(e);
});

function cellToRowCol(cell) {
  const col = cell.toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0);
  const row = parseInt(cell.slice(1)) - 1;
  return [col, row];
}

window.cellToRowCol = cellToRowCol;

function readExcelFile(event) {
  let input = event.target;
  let reader = new FileReader();
  reader.onload = function () {
    let data = new Uint8Array(reader.result);
    let workbook = XLSX.read(data, { type: 'array' });
    let worksheet = workbook.Sheets[workbook.SheetNames[0]];
    let jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
    let formData = mapExcelDataToFormData(jsonData);
    populateForm(formData);
  };
  if (input.files[0]) {
    reader.readAsArrayBuffer(input.files[0]);
  }
}

function mapExcelDataToFormData(data) {
  let formData = {};
  for (let field in fieldToCellMap) {
    let cell = fieldToCellMap[field];
    let rowIndex = parseInt(cell.substr(1)) - 1;
    let colIndex = cell.charCodeAt(0) - 65;
    formData[field] = data[rowIndex] && data[rowIndex][colIndex] !== undefined ? data[rowIndex][colIndex] : '';
  }
  return formData;
}

function readExcelFileOld(event) {
  let input = event.target;
  let reader = new FileReader();
  reader.onload = function () {
    let data = new Uint8Array(reader.result);
    let workbook = XLSX.read(data, { type: 'array' });
    let worksheet = workbook.Sheets[workbook.SheetNames[0]];
    let jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
    let formData = mapExcelDataToFormDataOld(jsonData);
    populateForm(formData);
  };
  if (input.files[0]) {
    reader.readAsArrayBuffer(input.files[0]);
  }
}

function mapExcelDataToFormDataOld(data) {
  let formData = {};
  for (let field in fieldToCellMapOld) {
    let cell = fieldToCellMapOld[field];
    let rowIndex = parseInt(cell.substr(1)) - 1;
    let colIndex = cell.charCodeAt(0) - 65;
    formData[field] = data[rowIndex] && data[rowIndex][colIndex] !== undefined ? data[rowIndex][colIndex] : '';
  }
  return formData;
}

function populateForm(data) {
  for (let field in data) {
    let input = byId(field);
    if (input) {
      input.value = data[field];
      savedData[input.id] = input.value;
      localStorage.setItem('collectorData', JSON.stringify(savedData));
    }
  }
  if (data.clientLastName && data.clientFirstName) {
    document.title = `${data.clientLastName}, ${data.clientFirstName}`;
  }
}

function trimSpaces(input) {
  input.value = input.value.trim();
}

window.trimSpaces = trimSpaces;

function titleCase(input) {
  input.value = input.value.trimStart();

  if (!input.getAttribute('data-corrected')) {
    input.value = input.value.trim().replace(/\b(\S+)\b/g, function (txt) {
      if (txt.length === 2) {
        const lowerCaseTxt = txt.toLowerCase();
        if (postalCode.hasOwnProperty(lowerCaseTxt)) {
          return txt.toUpperCase();
        } else if (specificTwoLetters.hasOwnProperty(lowerCaseTxt)) {
          return specificTwoLetters[lowerCaseTxt];
        } else {
          return txt;
        }
      }

      if (specificNames.hasOwnProperty(txt.toLowerCase())) {
        return specificNames[txt.toLowerCase()];
      }

      const mcMatch = txt.match(/^(mc)(.+)/i);
      if (mcMatch) {
        return 'Mc' + mcMatch[2].charAt(0).toUpperCase() + mcMatch[2].slice(1).toLowerCase();
      }

      const macMatch = txt.match(/^(mac)(.+)/i);
      if (macMatch) {
        return 'Mac' + macMatch[2].charAt(0).toUpperCase() + macMatch[2].slice(1).toLowerCase();
      }

      return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    });
    input.setAttribute('data-corrected', true);
  }
}

window.titleCase = titleCase;

function validateEmail(input) {
  const emailErrorElement = byId('emailError');
  const trimmedValue = input.value.trim().toLowerCase();

  if (trimmedValue !== '' && !input.getAttribute('data-corrected')) {
    var emailRegex = /^\S+@\S+\.\S+$/;

    if (!emailRegex.test(trimmedValue)) {
      if (emailErrorElement) emailErrorElement.textContent = 'Please enter a valid email address';
      input.focus();
      savedData[input.id] = trimmedValue;
      localStorage.setItem('collectorData', JSON.stringify(savedData));
      return false;
    } else {
      if (emailErrorElement) emailErrorElement.textContent = '';
    }

    input.setAttribute('data-corrected', 'true');
  } else {
    if (emailErrorElement) emailErrorElement.textContent = '';
  }

  input.value = trimmedValue;
}

window.validateEmail = validateEmail;

function formatPhone(input, type) {
  const typeToErrorElement = type === 'home' ? 'homePhoneError' : 'cellPhoneError';
  const phoneErrorElement = byId(typeToErrorElement);

  if (input.value.length > 0 && !input.getAttribute('data-corrected')) {
    let value = input.value.replace(/[^0-9]/g, '');
    if (/^\d{10}$/.test(value)) {
      input.value = value.slice(0, 3) + '-' + value.slice(3, 6) + '-' + value.slice(6);
      if (phoneErrorElement) phoneErrorElement.textContent = '';
      input.setAttribute('data-corrected', 'true');
    } else {
      input.value = '';
      if (phoneErrorElement) phoneErrorElement.textContent = 'Phone number must be 10 digits';
      input.focus();
      return false;
    }
  }

  savedData[input.id] = input.value;
  localStorage.setItem('collectorData', JSON.stringify(savedData));
  return true;
}

window.formatPhone = formatPhone;

function formatCurrency(input) {
  if (!input.getAttribute('data-corrected')) {
    let value = input.value.replace(/[^0-9.]/g, '');
    value = parseFloat(value).toFixed(2);
    input.value = isNaN(value) ? '' : value;
    savedData[input.id] = input.value;
    localStorage.setItem('collectorData', JSON.stringify(savedData));
    input.setAttribute('data-corrected', 'true');
  }
}

window.formatCurrency = formatCurrency;

function formatDateTime(input) {
  if (!input.getAttribute('data-corrected')) {
    let value = new Date(input.value);
    if (!isNaN(value.getTime())) {
      let formatted =
        value.toLocaleDateString(undefined, {
          day: '2-digit',
          month: '2-digit',
          year: 'numeric',
        }) +
        '; ' +
        value.toLocaleTimeString(undefined, {
          hour: '2-digit',
          minute: '2-digit',
          hour12: true,
        });
      input.value = formatted;
    }
    input.setAttribute('data-corrected', 'true');
  }
}

window.formatDateTime = formatDateTime;

function formatExpiration(input) {
  if (!input.getAttribute('data-corrected')) {
    let value = input.value.replace(/[^0-9]/g, '');
    if (value.length === 4) {
      input.value = value.slice(0, 2) + '/' + value.slice(2);
    }
    input.setAttribute('data-corrected', 'true');
  }
}

window.formatExpiration = formatExpiration;

function formatSSN(input, type) {
  const typeToErrorElement = type === 'client' ? 'clientSSNError' : 'client2SSNError';
  const ssnErrorElement = byId(typeToErrorElement);
  let lastFourDigits;
  let wholeSSN;

  if (input.value && !input.getAttribute('data-corrected')) {
    let value = input.value.replace(/[^0-9]/g, '');
    if (value.length === 9) {
      lastFourDigits = value.slice(5);
      input.value = value.slice(0, 3) + '-' + value.slice(3, 5) + '-' + lastFourDigits;
      savedData[input.id] = input.value;
      localStorage.setItem('collectorData', JSON.stringify(savedData));
      if (ssnErrorElement) ssnErrorElement.textContent = '';
    } else {
      input.value = '';
      if (ssnErrorElement) ssnErrorElement.textContent = 'SSN must be 9 digits';
      input.focus();
      return false;
    }
  }

  wholeSSN = input.value;
  return true;
}

window.formatSSN = formatSSN;

function formatState(input) {
  const stateErrorElement = byId('homeStateError');

  if (!input.getAttribute('data-corrected')) {
    const stateInput = input.value.trim().toUpperCase().replace(/\s+/g, ' ');
    const postalCode = stateToPostalCode[stateInput.toLowerCase()];

    if (postalCode) {
      input.value = postalCode.toUpperCase();
      if (stateErrorElement) stateErrorElement.textContent = '';
    } else if (Object.values(stateToPostalCode).includes(stateInput)) {
      input.value = stateInput;
      if (stateErrorElement) stateErrorElement.textContent = '';
    } else {
      if (stateErrorElement) stateErrorElement.textContent = 'Invalid state name or code';
      input.focus();
      return false;
    }

    savedData[input.id] = input.value;
    localStorage.setItem('collectorData', JSON.stringify(savedData));
  }
}

window.formatState = formatState;

function validateHomeZip(input) {
  let zip = input.value;
  let errorMessage = byId('zipError');

  if (zip.indexOf('-') !== -1 && zip.split('-')[1].length < 4) {
    zip = zip.substring(0, 5);
    input.value = zip;
  } else if (zip.indexOf('-') === -1 && zip.length > 5) {
    zip = zip.substring(0, 5);
    input.value = zip;
  }

  if (zip !== '' && !/^\d{5}(-\d{4})?$/.test(zip)) {
    if (errorMessage) errorMessage.textContent = 'Format as 12345 or 12345-1234';
    input.focus();
    return false;
  } else {
    if (errorMessage) errorMessage.textContent = '';
    return true;
  }
}

window.validateHomeZip = validateHomeZip;

function formatCaseState(input) {
  const stateErrorElement = byId('caseStateError');

  if (!input.getAttribute('data-corrected')) {
    const stateInput = input.value.trim().toUpperCase().replace(/\s+/g, ' ');
    const stateName = Object.keys(stateToPostalCode).find((key) => stateToPostalCode[key] === stateInput);

    if (stateName) {
      input.value = stateName.charAt(0).toUpperCase() + stateName.slice(1).toLowerCase();
      if (stateErrorElement) stateErrorElement.textContent = '';
    } else if (stateToPostalCode.hasOwnProperty(stateInput.toLowerCase())) {
      const fullStateName = Object.keys(stateToPostalCode).find((key) => stateToPostalCode[key] === stateInput);
      input.value = fullStateName.charAt(0).toUpperCase() + fullStateName.slice(1).toLowerCase();
      if (stateErrorElement) stateErrorElement.textContent = '';
    } else {
      if (stateErrorElement) stateErrorElement.textContent = 'Invalid state name or code';
      input.focus();
      return false;
    }

    savedData[input.id] = input.value;
    localStorage.setItem('collectorData', JSON.stringify(savedData));
  }
}

window.formatCaseState = formatCaseState;

onChange('excelFile', clearForm);
onChange('excelFileOld', clearForm);
onClick('clearForm', clearForm);

function clearForm() {
  let forms = document.getElementsByName('clientDataForm');
  if (forms.length > 0) {
    let form = forms[0];
    form.reset();
  }
  document.title = 'Client Intake Form';
  localStorage.removeItem('clientTitle');
}

function clearCaseInfo() {
  let caseFields = document.querySelectorAll('.case-info');
  caseFields.forEach((field) => {
    field.value = '';
    savedData[field.id] = '';
  });
  localStorage.setItem('collectorData', JSON.stringify(savedData));
}

onClick('clearCaseInfo', clearCaseInfo);

onClick('generateClientFolderBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-client-folder', data);
});

onSubmit('generateClientDataFile', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-excel', data, 'output.xlsx');
});

onClick('generatePaymentPlanBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-payment-plan', data, 'output.xlsx');
});

onClick('generateIcsBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-ics', data);
});

onClick('generateDiscoIcsMOBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-MOdisco-ics', data);
});

onClick('generateDiscoBtn', function (event) {
  generateDisco(event);
});

onClick('generateDiscoIcsKSBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-KSdisco-ics', data);
});

onClick('generateIcsBodyBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-ics-body', data);
});

onClick('generateContactBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-vCard', data);
});

onClick('generateRetainerBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-retainer', data);
});

onClick('generatePleadingBtn', function () {
  generatePleading();
});

onClick('generateLetterBtn', function () {
  generateLetter();
});

onClick('generateEoABtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-eoa', data);
});

onClick('generateNotesBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-notes', data);
});

onClick('generateSpreadsheetData', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-spreadsheet', data);
});

onClick('generateADsBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-ADs', data);
});

onClick('generateCloseOutBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-closeout', data);
});

onClick('generateServiceWaiverBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-waiver', data);
});

onClick('generateDisputeLetterBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-Dispute-Letter', data);
});

onClick('generateCannedEmailsBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-Canned-Emails', data);
});

onClick('generateDisputeEnvelopeBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-Dispute-Envelope', data);
});

onClick('generateDisputeCertBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-Dispute-Cert', data);
});

onClick('generateReminderICSBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-reminder-ics', data);
});

onClick('generateCreditAuthBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-credit-auth', data);
});

onClick('generateCreditAuthNoPaymentBtn', function (event) {
  event.preventDefault();
  const data = getFormData();
  sendFormData('/generate-credit-auth-no-payment', data);
});

function generatePleading() {
  var fileInput = byId('pleadingTemplateFile');
  var file = fileInput?.files?.[0];
  if (file) {
    var templateName = file.name.split('.').slice(0, -1).join('.');
    var data = getFormData();
    sendFormData('/generate-pleading', data, templateName);
  } else {
    alert('Please select a file before clicking Generate');
  }
}

function generateLetter() {
  var fileInput = byId('letterTemplateFile');
  var file = fileInput?.files?.[0];
  if (file) {
    var templateName = file.name.split('.').slice(0, -1).join('.');
    var data = getFormData();
    sendFormData('/generate-letter', data, templateName);
  } else {
    alert('Please select a file before clicking Generate');
  }
}

function generateDisco(event) {
  var fileInput = byId('discoTemplateFile');
  var file = fileInput?.files?.[0];
  if (file) {
    var templateName = file.name.split('.').slice(0, -1).join('.');
    var data = getFormData();
    sendFormData('/generate-disco', data, templateName);
  } else {
    alert('Please select a file before clicking Generate');
  }
}