import { ValidationHelpers, InputAdornment, HelpTooltip, __, sprintf } from '@vareoncalc/calculator-base';
import { getFormattingConfig, formatCurrencyHtml, formatCurrency, escapeHtml } from '../utils/formatting.js';
import { initCompactTwoStep } from '../utils/compact-two-step.js';

/**
 * Credit Card Payoff Calculator - "Debt Destruction Command Center"
 * Calculate payoff timeline with APR and monthly payment plan
 * Features: Strategy toggle (Fixed Payment vs Goal Date), visual bar, paged payment schedule
 */

export function paginateScheduleRows(schedule, rowsPerPage = 12) {
  if (!Array.isArray(schedule) || schedule.length === 0) {
    return [];
  }

  const safeRowsPerPage = Number.isFinite(rowsPerPage) && rowsPerPage > 0
    ? Math.floor(rowsPerPage)
    : 12;
  const pages = [];

  for (let i = 0; i < schedule.length; i += safeRowsPerPage) {
    pages.push(schedule.slice(i, i + safeRowsPerPage));
  }

  return pages;
}

export function mount(container) {
  const formatting = getFormattingConfig();
  const currencySymbol = escapeHtml(formatting.currencySymbol || '$');
  const moLabel = __('mo', 'vareon-calculator-suite-lite');
  const yrLabel = __('yr', 'vareon-calculator-suite-lite');
  const SCHEDULE_PAGE_SIZE = 12;
  const goalUnitToggle = `
    <span class="vareoncalc-term-units" data-goal-unit-toggle role="group" aria-label="${__('Payoff goal unit', 'vareon-calculator-suite-lite')}">
      <button type="button" class="vareoncalc-term-unit" data-goal-unit="months" aria-pressed="false">${__('Mo', 'vareon-calculator-suite-lite')}</button>
      <span class="vareoncalc-term-unit-divider" aria-hidden="true">/</span>
      <button type="button" class="vareoncalc-term-unit is-active" data-goal-unit="years" aria-pressed="true">${__('Yr', 'vareon-calculator-suite-lite')}</button>
    </span>
  `;

  // Compact two-step layout: inputs -> results + edit handle
  container.innerHTML = `
    <div class="vareoncalc-two-step vareoncalc-ccpayoff-dashboard" data-two-step data-two-step-mode="blind">
      <div class="vareoncalc-two-step__step vareoncalc-two-step__step--inputs" data-two-step-step="inputs">
        <div class="vareoncalc-two-step__inputs-body">
          <!-- LEFT PANEL: The Attack Plan -->
          <div class="vareoncalc-panel-input">
            <div class="vareoncalc-section ccpayoff-section">
              <div class="vareoncalc-section__header">
                <div class="vareoncalc-section__title">${__('Debt Plan', 'vareon-calculator-suite-lite')}</div>
              </div>
              <!-- The Enemy: Credit Card Balance -->
              <div class="vareoncalc-field vareoncalc-field--hero">
                <label for="balance">${__('Credit Card Balance', 'vareon-calculator-suite-lite')}</label>
              <input type="number" id="balance" data-suffix="${currencySymbol}" data-suffix-family="currency" placeholder="${__('e.g.', 'vareon-calculator-suite-lite')} 5000" min="0" step="10">
              </div>
              <!-- Strategy mode picker -->
              <div class="ccpayoff-strategy-switch" role="group" aria-label="${__('Payoff mode', 'vareon-calculator-suite-lite')}">
                <button type="button" class="strategy-btn strategy-btn--active" data-mode="payment">
                  <span class="strategy-label">${__('Fixed Payment', 'vareon-calculator-suite-lite')}</span>
                </button>
                <button type="button" class="strategy-btn" data-mode="goal">
                  <span class="strategy-label">${__('Goal Date', 'vareon-calculator-suite-lite')}</span>
                </button>
                <button type="button" class="strategy-btn" data-mode="minimum">
                  <span class="strategy-label">${__('Minimum Payment', 'vareon-calculator-suite-lite')}</span>
                </button>
              </div>
              <!-- APR + payment controls -->
              <div class="vareoncalc-field-row">
                <div class="vareoncalc-field">
                  <label for="apr" data-help="${__('Annual Percentage Rate - find this on your credit card statement or online account.', 'vareon-calculator-suite-lite')}">${__('APR', 'vareon-calculator-suite-lite')}</label>
                  <input type="number" id="apr" data-suffix="%" placeholder="${__('e.g.', 'vareon-calculator-suite-lite')} 18.99" min="0" max="100" step="0.01">
                </div>
                <div class="vareoncalc-field" id="payment-field">
                  <label for="payment" data-help="${__('The amount you plan to pay each month. Use more than your estimated minimum to see a faster payoff than minimum-only payments.', 'vareon-calculator-suite-lite')}">${__('Monthly Payment', 'vareon-calculator-suite-lite')}</label>
              <input type="number" id="payment" data-suffix="${currencySymbol}/${moLabel}" data-suffix-family="compound" placeholder="${__('e.g.', 'vareon-calculator-suite-lite')} 200" min="0" step="10">
                  <span class="ccpayoff-payment-min" id="payment-min-hint" hidden></span>
                </div>
                <div class="vareoncalc-field" id="months-field" style="display: none;">
                  <label for="months-goal" data-help="${__('How long you want to be debt-free in. We\'ll calculate the required payment.', 'vareon-calculator-suite-lite')}">${sprintf(
                    /* translators: %s: payoff goal unit toggle */
                    __('Payoff Goal (%s)', 'vareon-calculator-suite-lite'),
                    goalUnitToggle
                  )}</label>
                  <input type="number" id="months-goal" data-suffix="${yrLabel}" placeholder="${__('e.g.', 'vareon-calculator-suite-lite')} 2" min="1" max="10" step="1">
                </div>
              </div>
            </div>
            
            <!-- Calculate Button -->
            <button type="button" class="vareoncalc-btn" id="calc-btn" data-two-step-next>${__('Calculate Payoff', 'vareon-calculator-suite-lite')}</button>
          </div>
        </div>
      </div>

      <div class="vareoncalc-two-step__step vareoncalc-two-step__step--results" data-two-step-step="results" aria-hidden="true">
        <div class="vareoncalc-two-step__results">
          <!-- RIGHT PANEL: The Freedom Timeline -->
          <div class="vareoncalc-panel-result vareoncalc-ccpayoff-result" id="result-panel">
            <!-- Placeholder state -->
            <div class="ccpayoff-result__placeholder" id="result-placeholder">
              <div class="placeholder-icon">&#127919;</div>
              <div class="placeholder-text">${__('Enter your debt details to see your freedom timeline', 'vareon-calculator-suite-lite')}</div>
            </div>

            <!-- Results (hidden initially) -->
            <div class="ccpayoff-result__content" id="result-content" style="display: none;">
              <!-- Hero: two-column layout -->
              <div class="ccpayoff-hero">
                <!-- Left: Donut breakdown -->
                <div class="ccpayoff-hero__breakdown" role="img" aria-label="${__('Principal vs. Interest Breakdown', 'vareon-calculator-suite-lite')}">
                  <div class="ccpayoff-hero__title">${__('Principal vs. Interest Breakdown', 'vareon-calculator-suite-lite')}</div>
                  <div class="ccpayoff-donut">
                    <svg class="ccpayoff-donut__svg" viewBox="0 0 120 120">
                      <circle class="ccpayoff-donut__track" cx="60" cy="60" r="50" fill="none" stroke-width="20"/>
                      <circle class="ccpayoff-donut__segment ccpayoff-donut__segment--principal" id="donut-principal" cx="60" cy="60" r="50" fill="none" stroke-width="20" stroke-dasharray="0 314.16" stroke-dashoffset="78.54" transform="rotate(-90 60 60)"/>
                      <circle class="ccpayoff-donut__segment ccpayoff-donut__segment--interest" id="donut-interest" cx="60" cy="60" r="50" fill="none" stroke-width="20" stroke-dasharray="0 314.16" stroke-dashoffset="78.54" transform="rotate(-90 60 60)"/>
                      <text class="ccpayoff-donut__label" x="60" y="55" text-anchor="middle" dominant-baseline="auto">${__('Total:', 'vareon-calculator-suite-lite')}</text>
                      <text class="ccpayoff-donut__value" id="donut-total" x="60" y="70" text-anchor="middle" dominant-baseline="auto"></text>
                    </svg>
                  </div>
                  <div class="ccpayoff-donut__legend">
                    <div class="legend-item legend-item--principal">
                      <span class="legend-color"></span>
                      <span class="legend-label">${__('Principal:', 'vareon-calculator-suite-lite')}</span>
                      <span class="legend-amount" id="legend-principal-amt"></span>
                    </div>
                    <div class="legend-item legend-item--interest">
                      <span class="legend-color"></span>
                      <span class="legend-label">${__('Interest:', 'vareon-calculator-suite-lite')}</span>
                      <span class="legend-amount" id="legend-interest-amt"></span>
                    </div>
                  </div>
                </div>
                <!-- Right: Timeline -->
                <div class="ccpayoff-hero__timeline">
                  <div class="ccpayoff-hero__title">${__('Your Financial Escape Timeline', 'vareon-calculator-suite-lite')}</div>
                  <div class="ccpayoff-months" id="payoff-months"></div>
                  <div class="ccpayoff-date" id="payoff-date"></div>
                </div>
              </div>

              <div class="ccpayoff-warning" id="ccpayoff-warning" role="status" style="display: none;"></div>

              <!-- Summary Stats -->
              <div class="ccpayoff-summary">
                <div class="ccpayoff-stat">
                  <span class="stat-label">${__('Monthly Payment', 'vareon-calculator-suite-lite')}</span>
                  <span class="stat-value" id="summary-payment"></span>
                </div>
                <div class="ccpayoff-stat">
                  <span class="stat-label">${__('Total Cost', 'vareon-calculator-suite-lite')}</span>
                  <span class="stat-value" id="summary-total"></span>
                </div>
              </div>

              <!-- Payment Schedule -->
              <div class="ccpayoff-schedule">
                <button type="button" class="ccpayoff-schedule-header" id="ccpayoff-schedule-toggle" aria-expanded="false" aria-controls="ccpayoff-schedule-table">
                  <svg class="ccpayoff-schedule-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
                  <span class="ccpayoff-schedule-label">${__('Payment Schedule', 'vareon-calculator-suite-lite')}</span>
                </button>
                <div class="ccpayoff-schedule-body" id="ccpayoff-schedule-body" style="display: none;">
                  <div class="ccpayoff-schedule-table" id="ccpayoff-schedule-table"></div>
                  <div class="ccpayoff-schedule-controls" id="ccpayoff-schedule-controls">
                    <span class="ccpayoff-schedule-per-page">${sprintf(__('%d months per page', 'vareon-calculator-suite-lite'), SCHEDULE_PAGE_SIZE)}</span>
                    <div class="ccpayoff-schedule-pagination" id="ccpayoff-schedule-pagination">
                      <button type="button" class="ccpayoff-schedule-page-btn" id="ccpayoff-page-prev">${__('Previous', 'vareon-calculator-suite-lite')}</button>
                      <span class="ccpayoff-schedule-page-info" id="ccpayoff-page-info"></span>
                      <button type="button" class="ccpayoff-schedule-page-btn" id="ccpayoff-page-next">${__('Next', 'vareon-calculator-suite-lite')}</button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <button type="button" class="vareoncalc-two-step__blind-handle" data-two-step-toggle>
        <span class="vareoncalc-two-step__blind-handle-grip" aria-hidden="true"></span>
        <span>${__('Edit inputs', 'vareon-calculator-suite-lite')}</span>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m18 15-6-6-6 6"/></svg>
      </button>
    </div>
  `;

  InputAdornment.apply(container);
  HelpTooltip.apply(container);

  // DOM references
  const btn = container.querySelector('#calc-btn');
  const resultPlaceholder = container.querySelector('#result-placeholder');
  const resultContent = container.querySelector('#result-content');
  const resultPanel = container.querySelector('#result-panel');

  // Input fields
  const balanceInput = container.querySelector('#balance');
  const aprInput = container.querySelector('#apr');
  const paymentInput = container.querySelector('#payment');
  const monthsGoalInput = container.querySelector('#months-goal');
  const paymentField = container.querySelector('#payment-field');
  const paymentMinHint = container.querySelector('#payment-min-hint');
  const monthsField = container.querySelector('#months-field');
  const goalUnitButtons = Array.from(container.querySelectorAll('.vareoncalc-term-unit[data-goal-unit]'));
  [balanceInput, aprInput, paymentInput, monthsGoalInput].forEach((input) => {
    input?.closest('.vareoncalc-input-adorned')?.classList.add('vareoncalc-input-adorned--suffix-rail');
  });

  // Result elements
  const payoffMonthsEl = container.querySelector('#payoff-months');
  const payoffDateEl = container.querySelector('#payoff-date');
  const donutPrincipal = container.querySelector('#donut-principal');
  const donutInterest = container.querySelector('#donut-interest');
  const donutTotal = container.querySelector('#donut-total');
  const legendPrincipalAmt = container.querySelector('#legend-principal-amt');
  const legendInterestAmt = container.querySelector('#legend-interest-amt');
  const summaryPayment = container.querySelector('#summary-payment');
  const summaryTotal = container.querySelector('#summary-total');
  const warningEl = container.querySelector('#ccpayoff-warning');
  const scheduleToggle = container.querySelector('#ccpayoff-schedule-toggle');
  const scheduleBody = container.querySelector('#ccpayoff-schedule-body');
  const scheduleControls = container.querySelector('#ccpayoff-schedule-controls');
  const schedulePagination = container.querySelector('#ccpayoff-schedule-pagination');
  const pageInfo = container.querySelector('#ccpayoff-page-info');
  const pagePrevBtn = container.querySelector('#ccpayoff-page-prev');
  const pageNextBtn = container.querySelector('#ccpayoff-page-next');
  const scheduleTable = container.querySelector('#ccpayoff-schedule-table');
  const DONUT_CIRCUMFERENCE = 2 * Math.PI * 50;
  let twoStepInstance = null;
  const forEachTwoStepInstance = (handler) => {
    if (!twoStepInstance) {
      return;
    }
    if (Array.isArray(twoStepInstance)) {
      twoStepInstance.forEach(instance => {
        if (instance) {
          handler(instance);
        }
      });
      return;
    }
    handler(twoStepInstance);
  };
  const showResultsStep = () => {
    forEachTwoStepInstance((instance) => {
      if (typeof instance.setStep === 'function') {
        instance.setStep('results');
      }
      if (typeof instance.setDrawerOpen === 'function') {
        instance.setDrawerOpen(false);
      }
      if (typeof instance.refreshLayout === 'function') {
        instance.refreshLayout();
      }
    });
  };
  const refreshTwoStepLayout = () => {
    forEachTwoStepInstance((instance) => {
      if (typeof instance.refreshLayout === 'function') {
        instance.refreshLayout();
      }
    });
  };

  // Strategy toggle buttons
  const strategyBtns = container.querySelectorAll('.strategy-btn');
  let currentMode = 'payment'; // 'payment', 'goal', or 'minimum'
  let schedulePages = [];
  let currentSchedulePage = 0;

  // Strategy toggle handler
  strategyBtns.forEach(btn => {
    btn.addEventListener('click', () => {
      const mode = btn.dataset.mode;
      if (mode === currentMode) return;

      currentMode = mode;
      strategyBtns.forEach(b => b.classList.remove('strategy-btn--active'));
      btn.classList.add('strategy-btn--active');

      if (mode === 'payment') {
        paymentField.style.display = '';
        monthsField.style.display = 'none';
        refreshPaymentMinimumHint();
      } else if (mode === 'goal') {
        paymentField.style.display = 'none';
        monthsField.style.display = '';
      } else {
        paymentField.style.display = 'none';
        monthsField.style.display = 'none';
      }
    });
  });

  // Show error inline for the relevant input
  const showError = (input, message) => {
    if (!input) {
      return;
    }
    ValidationHelpers.showError(input, message);
    if (typeof input.focus === 'function') {
      input.focus();
    }
  };
  const showToastError = (input, message) => {
    ValidationHelpers.showToast(container, message);
    if (input && typeof input.focus === 'function') {
      input.focus();
    }
  };

  // Clear error
  const clearError = () => {
    ValidationHelpers.clearAllErrors(container);
    const errorEl = resultPanel.querySelector('.ccpayoff-error');
    if (errorEl) errorEl.style.display = 'none';
    if (warningEl) warningEl.style.display = 'none';
  };

  const MAX_GOAL_MONTHS = 120;
  const MAX_GOAL_YEARS = Math.floor(MAX_GOAL_MONTHS / 12);
  const MAX_MONTHS = 600;
  const WARN_MONTHS = 360;
  let goalTermUnit = 'years';
  const getGoalInputMax = () => (goalTermUnit === 'years' ? MAX_GOAL_YEARS : MAX_GOAL_MONTHS);
  const getGoalInputAsMonths = (goalValue) => (
    goalTermUnit === 'years'
      ? Math.round(goalValue * 12)
      : goalValue
  );
  const isValidGoalInput = (goalValue) => Number.isFinite(goalValue) && goalValue > 0 && goalValue <= getGoalInputMax();
  const getGoalValidationMessage = () => sprintf(
    /* translators: 1: maximum goal value, 2: selected goal unit */
    __('Please enter a valid payoff goal (1-%1$d %2$s).', 'vareon-calculator-suite-lite'),
    getGoalInputMax(),
    goalTermUnit === 'years'
      ? __('years', 'vareon-calculator-suite-lite')
      : __('months', 'vareon-calculator-suite-lite')
  );
  const setGoalTermUnit = (unit) => {
    goalTermUnit = unit === 'months' ? 'months' : 'years';
    if (monthsGoalInput) {
      monthsGoalInput.min = '1';
      monthsGoalInput.max = String(getGoalInputMax());
      monthsGoalInput.placeholder = goalTermUnit === 'years'
        ? `${__('e.g.', 'vareon-calculator-suite-lite')} 2`
        : `${__('e.g.', 'vareon-calculator-suite-lite')} 24`;
      InputAdornment.setSuffix(
        monthsGoalInput,
        goalTermUnit === 'years'
          ? __('yr', 'vareon-calculator-suite-lite')
          : __('mo', 'vareon-calculator-suite-lite')
      );
      ValidationHelpers.clearError(monthsGoalInput);
    }
    goalUnitButtons.forEach((button) => {
      const isActive = button.dataset.goalUnit === goalTermUnit;
      button.classList.toggle('is-active', isActive);
      button.setAttribute('aria-pressed', isActive ? 'true' : 'false');
      button.setAttribute('tabindex', isActive ? '0' : '-1');
    });
  };
  goalUnitButtons.forEach((button) => {
    button.addEventListener('click', () => {
      const nextUnit = button.dataset.goalUnit;
      if (!nextUnit || nextUnit === goalTermUnit) {
        return;
      }
      setGoalTermUnit(nextUnit);
    });
  });
  setGoalTermUnit('years');
  const syncGoalTermUnitState = () => {
    setGoalTermUnit(goalTermUnit || 'years');
  };
  const schedulePostMountGoalSync = () => {
    if (typeof requestAnimationFrame === 'function') {
      requestAnimationFrame(() => {
        syncGoalTermUnitState();
      });
      return;
    }
    setTimeout(() => {
      syncGoalTermUnitState();
    }, 0);
  };
  schedulePostMountGoalSync();

  const roundToCents = (value) => Math.round(value * 100) / 100;

  const calcMinimumPayment = (balance, interestCharge) => {
    const percentPayment = roundToCents(balance * 0.01);
    return Math.max(25, roundToCents(percentPayment + interestCharge));
  };

  /** Estimated first-month minimum (same rule as "Minimum Payment" strategy). */
  const getFirstMonthMinimumPayment = (balance, monthlyRate) => {
    if (!Number.isFinite(balance) || balance <= 0) {
      return 0;
    }
    const interestCharge = roundToCents(balance * monthlyRate);
    return calcMinimumPayment(balance, interestCharge);
  };

  const refreshPaymentMinimumHint = () => {
    if (!paymentMinHint) {
      return;
    }
    const balance = parseFloat(balanceInput.value);
    const apr = parseFloat(aprInput.value);
    if (!Number.isFinite(balance) || balance <= 0 || !Number.isFinite(apr) || apr < 0 || apr > 100) {
      paymentMinHint.textContent = '';
      paymentMinHint.hidden = true;
      return;
    }
    const monthlyRate = apr / 100 / 12;
    const estMin = getFirstMonthMinimumPayment(balance, monthlyRate);
    paymentMinHint.textContent = sprintf(
      /* translators: %s: formatted currency, estimated card minimum for current balance/APR */
      __('(est. minimum %s)', 'vareon-calculator-suite-lite'),
      formatCurrency(estMin)
    );
    paymentMinHint.hidden = false;
  };

  const buildPayoffSchedule = (balance, monthlyRate, mode, payment) => {
    let remainingBalance = roundToCents(balance);
    let totalPaid = 0;
    let totalInterest = 0;
    const schedule = [];
    let months = 0;
    let paidOff = false;

    for (let i = 1; i <= MAX_MONTHS && remainingBalance > 0.01; i++) {
      const interestCharge = roundToCents(remainingBalance * monthlyRate);
      const basePayment = mode === 'minimum'
        ? calcMinimumPayment(remainingBalance, interestCharge)
        : payment;
      let monthPayment = roundToCents(basePayment);

      if (monthlyRate > 0 && monthPayment <= interestCharge) {
        return {
          schedule,
          months,
          totalPaid,
          totalInterest,
          paidOff: false,
          error: __('Monthly payment must be greater than the minimum interest charge to pay off this balance.', 'vareon-calculator-suite-lite')
        };
      }

      let principalPayment = roundToCents(monthPayment - interestCharge);

      if (principalPayment >= remainingBalance) {
        monthPayment = roundToCents(remainingBalance + interestCharge);
        principalPayment = roundToCents(monthPayment - interestCharge);
        remainingBalance = 0;
        paidOff = true;
      } else {
        remainingBalance = roundToCents(remainingBalance - principalPayment);
      }

      totalPaid = roundToCents(totalPaid + monthPayment);
      totalInterest = roundToCents(totalInterest + interestCharge);
      months = i;

      schedule.push({
        month: i,
        payment: monthPayment,
        interest: interestCharge,
        principal: principalPayment,
        balance: remainingBalance
      });

      if (remainingBalance <= 0.01) {
        paidOff = true;
        break;
      }
    }

    return { schedule, months, totalPaid, totalInterest, paidOff };
  };

  // Calculate required payment for goal months
  const calcPaymentForGoal = (balance, monthlyRate, goalMonths) => {
    if (monthlyRate === 0) {
      return balance / goalMonths;
    }
    // PMT formula: PMT = P * [r(1+r)^n] / [(1+r)^n - 1]
    const factor = Math.pow(1 + monthlyRate, goalMonths);
    return balance * (monthlyRate * factor) / (factor - 1);
  };
  const canProceed = () => {
    const balance = parseFloat(balanceInput.value);
    const apr = parseFloat(aprInput.value);
    if (!Number.isFinite(balance) || balance <= 0) return false;
    if (!Number.isFinite(apr) || apr < 0 || apr > 100) return false;
    const monthlyRate = apr / 100 / 12;

    if (currentMode === 'payment') {
      const payment = parseFloat(paymentInput.value);
      if (!Number.isFinite(payment) || payment <= 0) return false;
      const estMin = getFirstMonthMinimumPayment(balance, monthlyRate);
      if (roundToCents(payment) <= roundToCents(estMin)) return false;
      return true;
    }
    if (currentMode === 'goal') {
      const goalValue = parseInt(monthsGoalInput.value, 10);
      if (!isValidGoalInput(goalValue)) return false;
      const goalMonths = getGoalInputAsMonths(goalValue);
      const payment = roundToCents(calcPaymentForGoal(balance, monthlyRate, goalMonths));
      if (!Number.isFinite(payment) || payment <= 0) return false;
      return true;
    }
    return true;
  };

  const applyCurrencyAdornments = () => {};

  const buildScheduleTable = (scheduleRows) => {
    if (!scheduleRows || !scheduleRows.length) {
      return '';
    }

    let html = `
      <table>
        <thead>
          <tr>
            <th>${__('Month', 'vareon-calculator-suite-lite')}</th>
            <th>${__('Interest', 'vareon-calculator-suite-lite')}</th>
            <th>${__('Principal', 'vareon-calculator-suite-lite')}</th>
            <th>${__('Balance', 'vareon-calculator-suite-lite')}</th>
          </tr>
        </thead>
        <tbody>
    `;

    scheduleRows.forEach((row) => {
      html += `
        <tr>
          <td>${row.month}</td>
          <td>${formatCurrencyHtml(row.interest)}</td>
          <td>${formatCurrencyHtml(row.principal)}</td>
          <td>${formatCurrencyHtml(row.balance)}</td>
        </tr>
      `;
    });

    html += `
        </tbody>
      </table>
    `;

    return html;
  };

  // Format months as human-readable
  const formatMonths = (months) => {
    const years = Math.floor(months / 12);
    const remainingMonths = months % 12;

    if (years === 0) {
      return sprintf(__('%d %s', 'vareon-calculator-suite-lite'), months, months === 1 ? __('month', 'vareon-calculator-suite-lite') : __('months', 'vareon-calculator-suite-lite'));
    } else if (remainingMonths === 0) {
      return sprintf(__('%d %s', 'vareon-calculator-suite-lite'), years, years === 1 ? __('year', 'vareon-calculator-suite-lite') : __('years', 'vareon-calculator-suite-lite'));
    } else {
      return sprintf(__('%d %s, %d %s', 'vareon-calculator-suite-lite'), years, years === 1 ? __('yr', 'vareon-calculator-suite-lite') : __('yrs', 'vareon-calculator-suite-lite'), remainingMonths, remainingMonths === 1 ? __('mo', 'vareon-calculator-suite-lite') : __('mos', 'vareon-calculator-suite-lite'));
    }
  };

  const setWarning = (message) => {
    if (!warningEl) return;
    if (!message) {
      warningEl.style.display = 'none';
      warningEl.textContent = '';
      return;
    }
    warningEl.textContent = message;
    warningEl.style.display = 'block';
  };

  const renderSchedulePage = () => {
    if (!scheduleTable) return;

    const totalPages = schedulePages.length;
    if (totalPages === 0) {
      scheduleTable.innerHTML = '';
      if (pageInfo) {
        pageInfo.textContent = '';
      }
      if (schedulePagination) {
        schedulePagination.style.display = 'none';
      }
      return;
    }

    if (currentSchedulePage < 0) {
      currentSchedulePage = 0;
    } else if (currentSchedulePage >= totalPages) {
      currentSchedulePage = totalPages - 1;
    }

    scheduleTable.innerHTML = buildScheduleTable(schedulePages[currentSchedulePage]);
    if (pageInfo) {
      pageInfo.textContent = sprintf(
        __('Page %1$d of %2$d', 'vareon-calculator-suite-lite'),
        currentSchedulePage + 1,
        totalPages
      );
    }
    if (pagePrevBtn) {
      pagePrevBtn.disabled = currentSchedulePage === 0;
    }
    if (pageNextBtn) {
      pageNextBtn.disabled = currentSchedulePage >= totalPages - 1;
    }
    if (schedulePagination) {
      schedulePagination.style.display = totalPages > 1 ? 'inline-flex' : 'none';
    }
  };

  const setScheduleExpanded = (expanded) => {
    if (!scheduleToggle || !scheduleBody) return;
    const hasSchedule = schedulePages.length > 0;

    scheduleToggle.setAttribute('aria-expanded', expanded ? 'true' : 'false');
    scheduleBody.style.display = expanded && hasSchedule ? 'block' : 'none';
  };

  const renderResults = (balance, payment, result) => {
    resultPlaceholder.style.display = 'none';
    resultContent.style.display = 'block';

    if (!result.paidOff) {
      payoffMonthsEl.textContent = __('Over 50 years', 'vareon-calculator-suite-lite');
      payoffDateEl.textContent = __('Payoff exceeds 50 years', 'vareon-calculator-suite-lite');
      setWarning(__('Payoff exceeds 50 years at this payment level. Increase payment to see a payoff date.', 'vareon-calculator-suite-lite'));
    } else {
      const payoffDate = new Date();
      payoffDate.setMonth(payoffDate.getMonth() + result.months);
      const dateOptions = { month: 'long', year: 'numeric' };
      payoffMonthsEl.textContent = formatMonths(result.months);
      payoffDateEl.innerHTML = sprintf(__('Debt Free by %s', 'vareon-calculator-suite-lite'), `<strong>${payoffDate.toLocaleDateString(undefined, dateOptions)}</strong>`);
      setWarning(result.months > WARN_MONTHS
        ? __('Heads up: this payoff takes more than 30 years.', 'vareon-calculator-suite-lite')
        : '');
    }

    const principalFrac = result.totalPaid > 0 ? balance / result.totalPaid : 1;
    const interestFrac = result.totalPaid > 0 ? result.totalInterest / result.totalPaid : 0;
    const principalArc = principalFrac * DONUT_CIRCUMFERENCE;
    const interestArc = interestFrac * DONUT_CIRCUMFERENCE;

    if (donutPrincipal) {
      donutPrincipal.setAttribute('stroke-dasharray', `${principalArc} ${DONUT_CIRCUMFERENCE}`);
      donutPrincipal.setAttribute('stroke-dashoffset', '0');
    }
    if (donutInterest) {
      donutInterest.setAttribute('stroke-dasharray', `${interestArc} ${DONUT_CIRCUMFERENCE}`);
      donutInterest.setAttribute('stroke-dashoffset', `${-principalArc}`);
    }
    if (donutTotal) {
      donutTotal.textContent = formatCurrency(result.totalPaid);
    }
    legendPrincipalAmt.innerHTML = formatCurrencyHtml(balance);
    legendInterestAmt.innerHTML = formatCurrencyHtml(result.totalInterest);

    const displayPayment = currentMode === 'minimum'
      ? (result.schedule[0] ? result.schedule[0].payment : 0)
      : payment;
    summaryPayment.innerHTML = formatCurrencyHtml(displayPayment);
    summaryTotal.innerHTML = formatCurrencyHtml(result.totalPaid);

    schedulePages = paginateScheduleRows(result.schedule, SCHEDULE_PAGE_SIZE);
    currentSchedulePage = 0;
    renderSchedulePage();
    setScheduleExpanded(false);

    showResultsStep();
  };

  const runCalculation = (event) => {
    if (event && typeof event.preventDefault === 'function') {
      event.preventDefault();
    }
    clearError();

    const invalidInputs = [];
    const messages = [];
    const recordInvalid = (input, message, options = {}) => {
      if (!input) {
        return;
      }
      ValidationHelpers.markInvalid(input, options);
      invalidInputs.push(input);
      if (message) {
        messages.push(message);
      }
    };

    const balance = parseFloat(balanceInput.value);
    const apr = parseFloat(aprInput.value);
    const monthlyRate = apr / 100 / 12;

    if (!balance || balance <= 0) {
      recordInvalid(balanceInput, __('Please enter a valid credit card balance.', 'vareon-calculator-suite-lite'), {
        validator: () => {
          const value = parseFloat(balanceInput.value);
          return Number.isFinite(value) && value > 0;
        },
      });
    }

    if (isNaN(apr) || apr < 0 || apr > 100) {
      recordInvalid(aprInput, __('Please enter a valid APR (0-100%).', 'vareon-calculator-suite-lite'), {
        validator: () => {
          const value = parseFloat(aprInput.value);
          return Number.isFinite(value) && value >= 0 && value <= 100;
        },
      });
    }

    let payment = 0;

    if (currentMode === 'payment') {
      payment = parseFloat(paymentInput.value);

      if (!payment || payment <= 0) {
        recordInvalid(paymentInput, __('Please enter a valid monthly payment.', 'vareon-calculator-suite-lite'), {
          validator: () => {
            const value = parseFloat(paymentInput.value);
            return Number.isFinite(value) && value > 0;
          },
        });
      }

      const estMinPay = getFirstMonthMinimumPayment(balance, monthlyRate);
      if (roundToCents(payment) <= roundToCents(estMinPay)) {
        recordInvalid(paymentInput, sprintf(
          /* translators: %s: formatted estimated minimum payment */
          __('Monthly payment must be greater than the estimated minimum (%s) for this balance.', 'vareon-calculator-suite-lite'),
          formatCurrency(estMinPay)
        ), {
          validator: () => {
            const currentBalance = parseFloat(balanceInput.value);
            const currentApr = parseFloat(aprInput.value);
            const currentPayment = parseFloat(paymentInput.value);
            if (!Number.isFinite(currentBalance) || currentBalance <= 0) return false;
            if (!Number.isFinite(currentApr) || currentApr < 0 || currentApr > 100) return false;
            if (!Number.isFinite(currentPayment) || currentPayment <= 0) return false;
            const rate = currentApr / 100 / 12;
            const min = getFirstMonthMinimumPayment(currentBalance, rate);
            return roundToCents(currentPayment) > roundToCents(min);
          },
        });
      }

      payment = roundToCents(payment);
    } else if (currentMode === 'goal') {
      const goalValue = parseInt(monthsGoalInput.value, 10);
      const goalMonths = getGoalInputAsMonths(goalValue);

      if (!isValidGoalInput(goalValue)) {
        recordInvalid(monthsGoalInput, getGoalValidationMessage(), {
          validator: () => {
            const value = parseInt(monthsGoalInput.value, 10);
            return isValidGoalInput(value);
          },
        });
      }

      payment = roundToCents(calcPaymentForGoal(balance, monthlyRate, goalMonths));

      if (!isFinite(payment) || payment <= 0) {
        recordInvalid(monthsGoalInput, __('Unable to calculate payment for this goal.', 'vareon-calculator-suite-lite'), {
          validator: () => {
            const value = parseInt(monthsGoalInput.value, 10);
            if (!isValidGoalInput(value)) {
              return false;
            }
            const valueMonths = getGoalInputAsMonths(value);
            const currentBalance = parseFloat(balanceInput.value);
            const currentApr = parseFloat(aprInput.value);
            if (!Number.isFinite(currentBalance) || currentBalance <= 0) return false;
            if (!Number.isFinite(currentApr) || currentApr < 0 || currentApr > 100) return false;
            const currentMonthlyRate = currentApr / 100 / 12;
            const computed = roundToCents(calcPaymentForGoal(currentBalance, currentMonthlyRate, valueMonths));
            return Number.isFinite(computed) && computed > 0;
          },
        });
      }
    }

    if (invalidInputs.length > 0) {
      const message = messages.length === 1
        ? messages[0]
        : __('Please fix the highlighted fields.', 'vareon-calculator-suite-lite');
      ValidationHelpers.showToast(container, message);
      return;
    }

    const baseResult = buildPayoffSchedule(balance, monthlyRate, currentMode, payment);
    if (baseResult.error) {
      const targetInput = currentMode === 'goal' ? monthsGoalInput : paymentInput;
      ValidationHelpers.markInvalid(targetInput, {
        validator: () => {
          const currentBalance = parseFloat(balanceInput.value);
          const currentApr = parseFloat(aprInput.value);
          if (!Number.isFinite(currentBalance) || currentBalance <= 0) return false;
          if (!Number.isFinite(currentApr) || currentApr < 0 || currentApr > 100) return false;
          if (currentMode === 'goal') {
            const value = parseInt(monthsGoalInput.value, 10);
          if (!isValidGoalInput(value)) return false;
          const computed = roundToCents(
            calcPaymentForGoal(currentBalance, currentApr / 100 / 12, getGoalInputAsMonths(value))
          );
            return Number.isFinite(computed) && computed > 0;
          }
          const currentPayment = parseFloat(paymentInput.value);
          if (!Number.isFinite(currentPayment) || currentPayment <= 0) return false;
          const rate = currentApr / 100 / 12;
          const min = getFirstMonthMinimumPayment(currentBalance, rate);
          return roundToCents(currentPayment) > roundToCents(min);
        },
      });
      ValidationHelpers.showToast(container, baseResult.error);
      return;
    }

    applyCurrencyAdornments();
    renderResults(balance, payment, baseResult);
  };

  applyCurrencyAdornments();

  scheduleToggle.addEventListener('click', () => {
    const expanded = scheduleToggle.getAttribute('aria-expanded') === 'true';
    setScheduleExpanded(!expanded);
    refreshTwoStepLayout();
  });
  if (pagePrevBtn) {
    pagePrevBtn.addEventListener('click', () => {
      if (currentSchedulePage <= 0) return;
      currentSchedulePage -= 1;
      renderSchedulePage();
      refreshTwoStepLayout();
    });
  }
  if (pageNextBtn) {
    pageNextBtn.addEventListener('click', () => {
      if (currentSchedulePage >= schedulePages.length - 1) return;
      currentSchedulePage += 1;
      renderSchedulePage();
      refreshTwoStepLayout();
    });
  }

  btn.addEventListener('click', runCalculation);

  [balanceInput, aprInput].forEach((inputEl) => {
    if (!inputEl) {
      return;
    }
    inputEl.addEventListener('input', refreshPaymentMinimumHint);
    inputEl.addEventListener('change', refreshPaymentMinimumHint);
  });
  refreshPaymentMinimumHint();

  twoStepInstance = initCompactTwoStep(container, { canProceed });
  if (twoStepInstance && typeof twoStepInstance.refreshLayout === 'function') {
    twoStepInstance.refreshLayout();
  }
}
