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

const TEXT_DOMAIN = 'vareon-calculator-suite-lite';
const TRASH_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>`;
const OVERWEIGHT_TOLERANCE = 0.0001;
const GRADE_SCALE = [
  { min: 90, letter: 'A', color: '#10b981' },
  { min: 80, letter: 'B', color: '#3b82f6' },
  { min: 70, letter: 'C', color: '#f59e0b' },
  { min: 60, letter: 'D', color: '#f97316' },
  { min: 0, letter: 'F', color: '#dc2626' }
];

function getGradeDescriptor(score) {
  return GRADE_SCALE.find((scale) => score >= scale.min) || GRADE_SCALE[GRADE_SCALE.length - 1];
}

function getGradeStatus(score) {
  if (score >= 90) {
    return __('Excellent', TEXT_DOMAIN);
  }
  if (score >= 80) {
    return __('Strong', TEXT_DOMAIN);
  }
  if (score >= 70) {
    return __('On Track', TEXT_DOMAIN);
  }
  if (score >= 60) {
    return __('Needs Improvement', TEXT_DOMAIN);
  }
  return __('At Risk', TEXT_DOMAIN);
}

function formatWeight(value) {
  const rounded = Math.round(value * 10) / 10;
  return Number.isInteger(rounded) ? String(rounded) : rounded.toFixed(1);
}

export function mount(container) {
  const layout = (window.VAREONCALC_CFG && window.VAREONCALC_CFG.layout) || 'compact';
  const isWide = layout === 'wide';

  if (isWide) {
    container.parentElement?.classList.add('layout-wide');
  }

  let assignments = [];
  let assignmentIdCounter = 0;
  let entryMode = 'weight';
  let editingAssignmentId = null;
  let twoStepInstance = null;

  container.innerHTML = `
    <div class="vareoncalc-two-step gradebook-two-step" 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">
          <div class="vareoncalc-panel-input gradebook-entry vareoncalc-section">
            <div class="gradebook-entry__section gradebook-section vareoncalc-section">
              <div class="vareoncalc-section__header gradebook-entry__header">
                <div class="gradebook-settings-inline-wrap">
                  <button
                    type="button"
                    class="gradebook-settings-btn"
                    id="gradebook-settings-btn"
                    aria-label="${__('Scenario settings', TEXT_DOMAIN)}"
                    aria-expanded="false"
                    aria-controls="gradebook-settings-modal"
                  >
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true" focusable="false">
                      <line x1="4" y1="21" x2="4" y2="14"></line>
                      <line x1="4" y1="10" x2="4" y2="3"></line>
                      <line x1="12" y1="21" x2="12" y2="13"></line>
                      <line x1="12" y1="9" x2="12" y2="3"></line>
                      <line x1="20" y1="21" x2="20" y2="17"></line>
                      <line x1="20" y1="13" x2="20" y2="3"></line>
                      <line x1="1" y1="14" x2="7" y2="14"></line>
                      <line x1="9" y1="9" x2="15" y2="9"></line>
                      <line x1="17" y1="16" x2="23" y2="16"></line>
                    </svg>
                  </button>
                </div>
                <div class="gradebook-entry__title-row">
                  <div class="vareoncalc-section__title gradebook-entry__title">${__('Gradebook Setup', TEXT_DOMAIN)}</div>
                  <div
                    class="gradebook-mode-toggle vareoncalc-measurement-toggle"
                    data-gradebook-mode-toggle
                    data-mode="weight"
                    data-active="weight"
                    role="group"
                    aria-label="${__('Grade entry mode', TEXT_DOMAIN)}"
                  >
                    <button
                      type="button"
                      class="gradebook-mode-toggle__btn vareoncalc-measurement-toggle__btn is-active vareoncalc-measurement-toggle__btn--active"
                      data-gradebook-mode-option="weight"
                      aria-pressed="true"
                    >
                      ${__('By Weight', TEXT_DOMAIN)}
                    </button>
                    <button
                      type="button"
                      class="gradebook-mode-toggle__btn vareoncalc-measurement-toggle__btn"
                      data-gradebook-mode-option="points"
                      aria-pressed="false"
                    >
                      ${__('By Points', TEXT_DOMAIN)}
                    </button>
                  </div>
                </div>
                <div class="gradebook-weight-indicator" id="weight-indicator" role="status" aria-live="polite">
                  <span class="gradebook-weight-indicator__prefix">${__('Total:', TEXT_DOMAIN)}</span>
                  <span class="gradebook-weight-indicator__value">0%</span>
                  <span class="gradebook-weight-indicator__label">${__('entered', TEXT_DOMAIN)}</span>
                </div>
              </div>

              <div class="gradebook-quick-add gradebook-section vareoncalc-section">
                <input type="text" id="new-assignment-name" class="gradebook-input gradebook-input--name" placeholder="${__('Assignment Name', TEXT_DOMAIN)}" title="${__('Enter the assignment name', TEXT_DOMAIN)}" maxlength="50">
                <input type="number" id="new-assignment-score" class="gradebook-input gradebook-input--score" placeholder="${__('Score', TEXT_DOMAIN)}" title="${__('Enter score as a percent (0-100)', TEXT_DOMAIN)}" min="0" max="150" step="0.1">
                <input type="number" id="new-assignment-weight" class="gradebook-input gradebook-input--weight" placeholder="${__('Weight', TEXT_DOMAIN)}" title="${__('Enter assignment weight as a percent of the course', TEXT_DOMAIN)}" min="0" step="0.5">
                <button type="button" class="gradebook-add-btn" id="add-assignment-btn" title="${__('Add Assignment', TEXT_DOMAIN)}">
                  <span class="gradebook-add-btn__icon">+</span>
                </button>
              </div>

              <div class="gradebook-list-shell gradebook-section vareoncalc-section">
                <div class="gradebook-list-header">
                  <div class="gradebook-list-header__name">${__('Assignment', TEXT_DOMAIN)}</div>
                  <div class="gradebook-list-header__score" id="gradebook-list-score-label">${__('Score', TEXT_DOMAIN)}</div>
                  <div class="gradebook-list-header__weight" id="gradebook-list-weight-label">${__('Weight', TEXT_DOMAIN)}</div>
                  <div class="gradebook-list-header__action" title="${__('Remove', TEXT_DOMAIN)}">${TRASH_ICON}</div>
                </div>
                <div class="gradebook-assignment-list" id="assignments-list"></div>
              </div>

              <div class="gradebook-entry__footer">
                <button type="button" class="gradebook-remaining-btn" id="add-remaining-btn">${__('Add Remaining Weight as Final', TEXT_DOMAIN)}</button>
                <div class="gradebook-remaining" id="remaining-helper" hidden>
                  <span class="gradebook-remaining__text"></span>
                </div>
              </div>
            </div>

            <div class="gradebook-step-actions vareoncalc-section">
              <button type="button" class="vareoncalc-btn" id="gradebook-next-btn" data-two-step-next disabled>
                ${__('Calculate Required Score', TEXT_DOMAIN)}
              </button>
            </div>
          </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 gradebook-results-step">
          <div class="vareoncalc-panel-result vareoncalc-gradebook-report vareoncalc-gradebook-report--placeholder" id="result-panel">
            <div class="gradebook-empty-state">
              <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
                <path d="M4 4h16v16H4z"></path>
                <path d="M8 9h8M8 13h8M8 17h5"></path>
              </svg>
              <p>${__('Add assignments in Step 1 to build your report card.', TEXT_DOMAIN)}</p>
            </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 gradebook entries', TEXT_DOMAIN)}</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"></path>
        </svg>
      </button>

      <div class="gradebook-settings-modal" id="gradebook-settings-modal" hidden>
        <div class="gradebook-settings-modal__backdrop" id="gradebook-settings-modal-backdrop"></div>
        <div class="gradebook-settings-modal__container" role="dialog" aria-modal="true" aria-labelledby="gradebook-settings-modal-title">
          <div class="gradebook-settings-modal__header">
            <div class="gradebook-settings-modal__title-group">
              <h3 class="gradebook-settings-modal__title" id="gradebook-settings-modal-title">${__('Scenario Settings', TEXT_DOMAIN)}</h3>
              <p class="gradebook-settings-modal__subtitle">${__('Set your target grade to forecast what score you need on remaining coursework.', TEXT_DOMAIN)}</p>
            </div>
            <button type="button" class="gradebook-settings-modal__close" id="gradebook-settings-modal-close" aria-label="${__('Close', TEXT_DOMAIN)}">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true" focusable="false">
                <line x1="18" y1="6" x2="6" y2="18"></line>
                <line x1="6" y1="6" x2="18" y2="18"></line>
              </svg>
            </button>
          </div>

          <div class="gradebook-settings-modal__body">
            <div class="gradebook-goal-card vareoncalc-section" data-goal-card="target">
              <div class="gradebook-goal-card__header">
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true" focusable="false">
                  <circle cx="12" cy="12" r="10"></circle>
                  <circle cx="12" cy="12" r="6"></circle>
                  <circle cx="12" cy="12" r="2"></circle>
                </svg>
                <div class="gradebook-goal-card__header-copy">
                  <span class="gradebook-goal-card__eyebrow">${__('Target Planning', TEXT_DOMAIN)}</span>
                </div>
              </div>
              <div class="gradebook-goal-card__body" id="gradebook-goal-panel">
                <div class="gradebook-goal-primary">
                  <div class="gradebook-goal-grid">
                    <div class="vareoncalc-field">
                      <label for="desired-grade">${__('Desired Final Grade', TEXT_DOMAIN)}</label>
                      <input type="number" id="desired-grade" class="gradebook-input" data-suffix="%" placeholder="90" min="0" max="100" step="0.1">
                    </div>
                  </div>
                </div>
                <div class="gradebook-goal-actions-wrap">
                  <span class="gradebook-goal-actions__label">${__('Quick targets', TEXT_DOMAIN)}</span>
                  <div class="gradebook-goal-actions">
                    <button type="button" class="gradebook-goal-btn" data-goal="60">${__('Calculate for Passing (60%)', TEXT_DOMAIN)}</button>
                    <button type="button" class="gradebook-goal-btn" data-goal="90">${__('Calculate for A (90%)', TEXT_DOMAIN)}</button>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div class="gradebook-settings-modal__footer">
            <button type="button" class="vareoncalc-btn" id="gradebook-settings-modal-done">${__('Done', TEXT_DOMAIN)}</button>
          </div>
        </div>
      </div>
    </div>
  `;

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

  const newAssignmentNameInput = container.querySelector('#new-assignment-name');
  const newAssignmentScoreInput = container.querySelector('#new-assignment-score');
  const newAssignmentWeightInput = container.querySelector('#new-assignment-weight');
  const addAssignmentBtn = container.querySelector('#add-assignment-btn');
  const addRemainingBtn = container.querySelector('#add-remaining-btn');
  const modeToggle = container.querySelector('[data-gradebook-mode-toggle]');
  const modeWeightOption = container.querySelector('[data-gradebook-mode-option="weight"]');
  const modePointsOption = container.querySelector('[data-gradebook-mode-option="points"]');
  const listScoreLabel = container.querySelector('#gradebook-list-score-label');
  const listWeightLabel = container.querySelector('#gradebook-list-weight-label');
  const assignmentsList = container.querySelector('#assignments-list');
  const desiredGradeInput = container.querySelector('#desired-grade');
  desiredGradeInput?.closest('.vareoncalc-input-adorned')?.classList.add('vareoncalc-input-adorned--suffix-rail');

  const nextBtn = container.querySelector('#gradebook-next-btn');
  const resultPanel = container.querySelector('#result-panel');
  const weightIndicator = container.querySelector('#weight-indicator .gradebook-weight-indicator__value');
  const weightIndicatorLabel = container.querySelector('#weight-indicator .gradebook-weight-indicator__label');
  const remainingHelper = container.querySelector('#remaining-helper');
  const remainingHelperText = container.querySelector('#remaining-helper .gradebook-remaining__text');
  const goalButtons = Array.from(container.querySelectorAll('.gradebook-goal-btn'));
  const goalCard = container.querySelector('[data-goal-card="target"]');
  const twoStepRoot = container.querySelector('.gradebook-two-step');

  const settingsButton = container.querySelector('#gradebook-settings-btn');
  const settingsModal = container.querySelector('#gradebook-settings-modal');
  const settingsModalBackdrop = container.querySelector('#gradebook-settings-modal-backdrop');
  const settingsModalClose = container.querySelector('#gradebook-settings-modal-close');
  const settingsModalDone = container.querySelector('#gradebook-settings-modal-done');

  const desiredGradeValidator = () => {
    const raw = desiredGradeInput?.value.trim() || '';
    if (raw === '') {
      return true;
    }
    const value = parseFloat(raw);
    return Number.isFinite(value) && value >= 0 && value <= 100;
  };

  function refreshTwoStepLayout() {
    if (twoStepInstance && typeof twoStepInstance.refreshLayout === 'function') {
      twoStepInstance.refreshLayout();
    }
  }

  function isResultsStepActive() {
    const state = twoStepInstance && typeof twoStepInstance.getState === 'function'
      ? twoStepInstance.getState()
      : null;
    if (state && state.step) {
      return state.step === 'results';
    }
    return twoStepRoot?.dataset.step === 'results';
  }

  function getTotalWeight() {
    return assignments.reduce((sum, assignment) => sum + assignment.weight, 0);
  }

  function parseDesiredGrade({ markInvalid = false } = {}) {
    const raw = desiredGradeInput?.value.trim() || '';
    if (raw === '') {
      ValidationHelpers.clearInvalid(desiredGradeInput);
      return { valid: true, value: null };
    }

    const value = parseFloat(raw);
    if (!Number.isFinite(value) || value < 0 || value > 100) {
      const message = __('Desired grade must be between 0 and 100.', TEXT_DOMAIN);
      if (markInvalid && desiredGradeInput) {
        ValidationHelpers.markInvalid(desiredGradeInput, {
          allowEmpty: true,
          validator: desiredGradeValidator
        });
        ValidationHelpers.showToast(container, message, { type: 'error' });
      }
      return { valid: false, value: null, message };
    }

    ValidationHelpers.clearInvalid(desiredGradeInput);
    return { valid: true, value };
  }

  function updateGoalCardState() {
    if (!goalCard || !desiredGradeInput) {
      return;
    }
    goalCard.classList.toggle('is-active', desiredGradeInput.value.trim() !== '');
  }

  function isPointsMode() {
    return entryMode === 'points';
  }

  function getAssignmentDisplayValues(assignment) {
    if (isPointsMode()) {
      return {
        score: (assignment.score * assignment.weight) / 100,
        weight: assignment.weight
      };
    }
    return {
      score: assignment.score,
      weight: assignment.weight
    };
  }

  function updateModeToggleState() {
    if (!modeToggle || !modeWeightOption || !modePointsOption) {
      return;
    }

    modeToggle.setAttribute('data-mode', entryMode);
    modeToggle.setAttribute('data-active', entryMode);

    [
      { button: modeWeightOption, mode: 'weight' },
      { button: modePointsOption, mode: 'points' }
    ].forEach(({ button, mode }) => {
      const isActive = mode === entryMode;
      button.setAttribute('aria-pressed', isActive ? 'true' : 'false');
      button.classList.toggle('is-active', isActive);
      button.classList.toggle('vareoncalc-measurement-toggle__btn--active', isActive);
      button.setAttribute('tabindex', isActive ? '0' : '-1');
    });
  }

  function updateQuickAddCopy() {
    const pointsMode = isPointsMode();

    if (newAssignmentNameInput) {
      newAssignmentNameInput.setAttribute('title', __('Enter the assignment name', TEXT_DOMAIN));
    }

    if (newAssignmentScoreInput) {
      newAssignmentScoreInput.placeholder = pointsMode
        ? __('Points Earned', TEXT_DOMAIN)
        : __('Score', TEXT_DOMAIN);
      newAssignmentScoreInput.setAttribute(
        'aria-label',
        pointsMode ? __('Points Earned', TEXT_DOMAIN) : __('Score', TEXT_DOMAIN)
      );
      newAssignmentScoreInput.setAttribute(
        'title',
        pointsMode
          ? __('Enter points earned for this assignment', TEXT_DOMAIN)
          : __('Enter score as a percent (0-100)', TEXT_DOMAIN)
      );
      if (pointsMode) {
        newAssignmentScoreInput.removeAttribute('max');
      } else {
        newAssignmentScoreInput.setAttribute('max', '150');
      }
    }

    if (newAssignmentWeightInput) {
      newAssignmentWeightInput.placeholder = pointsMode
        ? __('Points Possible', TEXT_DOMAIN)
        : __('Weight', TEXT_DOMAIN);
      newAssignmentWeightInput.setAttribute(
        'aria-label',
        pointsMode ? __('Points Possible', TEXT_DOMAIN) : __('Weight', TEXT_DOMAIN)
      );
      newAssignmentWeightInput.setAttribute(
        'title',
        pointsMode
          ? __('Enter total points possible for this assignment', TEXT_DOMAIN)
          : __('Enter assignment weight as a percent of the course', TEXT_DOMAIN)
      );
    }

    if (listScoreLabel) {
      listScoreLabel.textContent = pointsMode
        ? __('Points Earned', TEXT_DOMAIN)
        : __('Score', TEXT_DOMAIN);
    }

    if (listWeightLabel) {
      listWeightLabel.textContent = pointsMode
        ? __('Points Possible', TEXT_DOMAIN)
        : __('Weight', TEXT_DOMAIN);
    }

    if (addRemainingBtn) {
      addRemainingBtn.textContent = pointsMode
        ? __('Add Remaining Points as Final', TEXT_DOMAIN)
        : __('Add Remaining Weight as Final', TEXT_DOMAIN);
    }
  }

  function updateAddAssignmentButtonState() {
    if (!addAssignmentBtn) {
      return;
    }
    const label = editingAssignmentId === null
      ? __('Add Assignment', TEXT_DOMAIN)
      : __('Save Assignment', TEXT_DOMAIN);
    addAssignmentBtn.title = label;
    addAssignmentBtn.setAttribute('aria-label', label);
    addAssignmentBtn.classList.toggle('gradebook-add-btn--editing', editingAssignmentId !== null);
  }

  function clearAssignmentDraft({ keepName = false } = {}) {
    if (!newAssignmentNameInput || !newAssignmentScoreInput || !newAssignmentWeightInput) {
      return;
    }

    if (!keepName) {
      newAssignmentNameInput.value = '';
    }
    newAssignmentScoreInput.value = '';
    newAssignmentWeightInput.value = '';

    ValidationHelpers.clearInvalid(newAssignmentScoreInput);
    ValidationHelpers.clearInvalid(newAssignmentWeightInput);
  }

  function clearEditingState({ clearDraft = false } = {}) {
    editingAssignmentId = null;
    updateAddAssignmentButtonState();
    if (clearDraft) {
      clearAssignmentDraft();
    }
  }

  function loadAssignmentIntoDraft(assignment) {
    if (!newAssignmentNameInput || !newAssignmentScoreInput || !newAssignmentWeightInput) {
      return;
    }

    const displayValues = getAssignmentDisplayValues(assignment);
    newAssignmentNameInput.value = assignment.name;
    newAssignmentScoreInput.value = formatWeight(displayValues.score);
    newAssignmentWeightInput.value = formatWeight(displayValues.weight);

    ValidationHelpers.clearInvalid(newAssignmentScoreInput);
    ValidationHelpers.clearInvalid(newAssignmentWeightInput);
  }

  function beginEditingAssignment(assignmentId) {
    const assignment = assignments.find((item) => item.id === assignmentId);
    if (!assignment || !newAssignmentNameInput) {
      return;
    }

    editingAssignmentId = assignment.id;
    loadAssignmentIntoDraft(assignment);
    updateAddAssignmentButtonState();
    renderAssignments();
    newAssignmentNameInput.focus();
  }

  function updateAddRemainingButton(remainingWeight, isOverweight) {
    if (!addRemainingBtn) {
      return;
    }
    const canUse = remainingWeight > 0 && !isOverweight;
    addRemainingBtn.disabled = !canUse;
    addRemainingBtn.classList.toggle('gradebook-remaining-btn--disabled', !canUse);
  }

  function updateNextButtonState() {
    if (!nextBtn) {
      return;
    }
    nextBtn.disabled = assignments.length === 0;
  }

  function updateWeightIndicator() {
    const totalWeight = getTotalWeight();
    const isOverweight = totalWeight > 100 + OVERWEIGHT_TOLERANCE;
    const remainingWeight = 100 - totalWeight;
    const totalDisplay = formatWeight(totalWeight);
    const pointsMode = isPointsMode();

    if (weightIndicator) {
      if (pointsMode || isOverweight) {
        weightIndicator.textContent = totalDisplay;
      } else {
        weightIndicator.textContent = `${totalDisplay}%`;
      }
    }
    if (weightIndicatorLabel) {
      if (pointsMode) {
        weightIndicatorLabel.textContent = __('points', TEXT_DOMAIN);
      } else {
        weightIndicatorLabel.textContent = isOverweight
          ? __('total', TEXT_DOMAIN)
          : __('entered', TEXT_DOMAIN);
      }
    }

    if (!isOverweight && remainingWeight > 0 && assignments.length > 0) {
      if (remainingHelper) {
        remainingHelper.hidden = false;
      }
      if (remainingHelperText) {
        remainingHelperText.textContent = pointsMode
          ? sprintf(
            __('You have %s points remaining to reach 100', TEXT_DOMAIN),
            formatWeight(remainingWeight)
          )
          : sprintf(
            __('You have %s%% of the course remaining', TEXT_DOMAIN),
            formatWeight(remainingWeight)
          );
      }
    } else if (remainingHelper) {
      remainingHelper.hidden = true;
    }

    updateAddRemainingButton(remainingWeight, isOverweight);
  }

  const settingsModalPlaceholder = document.createComment('gradebook-settings-modal');
  const settingsThemeRoot = container.closest('.vareoncalc-root');

  const SETTINGS_MODAL_THEME_VARS = [
    '--vareoncalc-input-bg',
    '--vareoncalc-input-text',
    '--vareoncalc-input-border',
    '--vareoncalc-card-text',
    '--vareoncalc-card-bg',
    '--vareoncalc-card-border',
    '--vareoncalc-accent',
    '--vareoncalc-muted-text',
    '--sc-input-bg',
    '--sc-input-border',
    '--sc-input-text',
    '--sc-card-text',
    '--sc-card-bg',
    '--sc-card-border',
    '--sc-accent',
    '--sc-muted-text',
    '--sc-button-bg',
    '--sc-button-text',
    '--sc-button-hover'
  ];

  function syncSettingsModalThemeVars() {
    if (!settingsModal || !settingsThemeRoot) {
      return;
    }
    const cs = getComputedStyle(settingsThemeRoot);
    SETTINGS_MODAL_THEME_VARS.forEach((prop) => {
      const value = cs.getPropertyValue(prop).trim();
      if (value) {
        settingsModal.style.setProperty(prop, value);
      }
    });
  }

  function clearSettingsModalThemeVars() {
    if (!settingsModal) {
      return;
    }
    SETTINGS_MODAL_THEME_VARS.forEach((prop) => settingsModal.style.removeProperty(prop));
  }

  function setSettingsModalState(isOpen, { returnFocus = false } = {}) {
    if (!settingsModal || !settingsButton) {
      return;
    }

    if (isOpen) {
      settingsModal.parentNode.insertBefore(settingsModalPlaceholder, settingsModal);
      syncSettingsModalThemeVars();
      document.body.appendChild(settingsModal);
      settingsModal.removeAttribute('hidden');
      document.body.style.overflow = 'hidden';
    } else {
      settingsModal.setAttribute('hidden', '');
      document.body.style.overflow = '';
      clearSettingsModalThemeVars();
      if (settingsModalPlaceholder.parentNode) {
        settingsModalPlaceholder.parentNode.insertBefore(settingsModal, settingsModalPlaceholder);
        settingsModalPlaceholder.parentNode.removeChild(settingsModalPlaceholder);
      }
    }

    settingsButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
    settingsButton.classList.toggle('is-active', isOpen);
    refreshTwoStepLayout();

    if (isOpen && settingsModalClose) {
      setTimeout(() => settingsModalClose.focus(), 0);
    }
    if (!isOpen && returnFocus) {
      setTimeout(() => settingsButton.focus(), 0);
    }
  }

  function renderAssignments() {
    if (!assignmentsList) {
      return;
    }

    if (editingAssignmentId !== null && !assignments.some((assignment) => assignment.id === editingAssignmentId)) {
      clearEditingState({ clearDraft: true });
    }

    if (assignments.length === 0) {
      assignmentsList.innerHTML = `
        <div class="gradebook-empty">
          <div class="gradebook-empty__text">${__('No assignments added yet', TEXT_DOMAIN)}</div>
        </div>
      `;
      updateWeightIndicator();
      updateNextButtonState();
      updateAddAssignmentButtonState();
      refreshTwoStepLayout();
      return;
    }

    const pointsMode = isPointsMode();
    const totalWeight = getTotalWeight();
    const showPercent = !pointsMode && totalWeight <= 100 + OVERWEIGHT_TOLERANCE;

    assignmentsList.innerHTML = assignments.map((assignment) => {
      const displayValues = getAssignmentDisplayValues(assignment);
      const scoreSuffix = showPercent ? '%' : '';
      const weightSuffix = showPercent ? '%' : '';
      const isEditing = assignment.id === editingAssignmentId;
      const editLabel = sprintf(__('Edit %s', TEXT_DOMAIN), assignment.name);

      return `
      <div
        class="gradebook-assignment-row${isEditing ? ' gradebook-assignment-row--editing' : ''}"
        data-id="${assignment.id}"
        role="button"
        tabindex="0"
        aria-label="${escapeAttribute(editLabel)}"
      >
        <div class="gradebook-assignment-row__name" title="${escapeHtml(assignment.name)}">${escapeHtml(assignment.name)}</div>
        <div class="gradebook-assignment-row__score" data-label="${escapeAttribute(__('Score', TEXT_DOMAIN))}">${formatWeight(displayValues.score)}${scoreSuffix}</div>
        <div class="gradebook-assignment-row__weight" data-label="${escapeAttribute(__('Weight', TEXT_DOMAIN))}">${formatWeight(displayValues.weight)}${weightSuffix}</div>
        <button type="button" class="gradebook-remove-btn" data-id="${assignment.id}" title="${__('Remove', TEXT_DOMAIN)}">
          ${TRASH_ICON}
        </button>
      </div>
    `;
    }).join('');

    container.querySelectorAll('.gradebook-remove-btn').forEach((button) => {
      button.addEventListener('click', (event) => {
        event.stopPropagation();
        const id = Number.parseInt(button.getAttribute('data-id') || '', 10);
        if (!Number.isFinite(id)) {
          return;
        }
        if (editingAssignmentId === id) {
          clearEditingState({ clearDraft: true });
        }
        assignments = assignments.filter((assignment) => assignment.id !== id);
        renderAssignments();
        if (isResultsStepActive()) {
          calculateAndRender();
        }
      });
    });

    container.querySelectorAll('.gradebook-assignment-row').forEach((row) => {
      const id = Number.parseInt(row.getAttribute('data-id') || '', 10);
      if (!Number.isFinite(id)) {
        return;
      }

      row.addEventListener('click', (event) => {
        if (event.target instanceof Element && event.target.closest('.gradebook-remove-btn')) {
          return;
        }
        beginEditingAssignment(id);
      });

      row.addEventListener('keydown', (event) => {
        if (event.key !== 'Enter' && event.key !== ' ') {
          return;
        }
        event.preventDefault();
        beginEditingAssignment(id);
      });
    });

    updateWeightIndicator();
    updateNextButtonState();
    updateAddAssignmentButtonState();
    refreshTwoStepLayout();
  }

  function parseAssignmentDraft() {
    if (!newAssignmentNameInput || !newAssignmentScoreInput || !newAssignmentWeightInput) {
      return { valid: false, value: null };
    }

    const name = newAssignmentNameInput.value.trim() || __('Unnamed', TEXT_DOMAIN);
    const scoreInputValue = parseFloat(newAssignmentScoreInput.value);
    const weightInputValue = parseFloat(newAssignmentWeightInput.value);

    if (!Number.isFinite(scoreInputValue) || scoreInputValue < 0) {
      ValidationHelpers.markInvalid(newAssignmentScoreInput, { allowEmpty: false });
      newAssignmentScoreInput.focus();
      return { valid: false, value: null };
    }
    ValidationHelpers.clearInvalid(newAssignmentScoreInput);

    if (!Number.isFinite(weightInputValue) || weightInputValue <= 0) {
      ValidationHelpers.markInvalid(newAssignmentWeightInput, { allowEmpty: false });
      newAssignmentWeightInput.focus();
      return { valid: false, value: null };
    }
    ValidationHelpers.clearInvalid(newAssignmentWeightInput);

    const normalizedScore = isPointsMode()
      ? (scoreInputValue / weightInputValue) * 100
      : scoreInputValue;

    return {
      valid: true,
      value: {
        name,
        score: normalizedScore,
        weight: weightInputValue
      }
    };
  }

  function hasValidDraftValues() {
    const scoreValue = parseFloat(newAssignmentScoreInput?.value || '');
    const weightValue = parseFloat(newAssignmentWeightInput?.value || '');
    return Number.isFinite(scoreValue) && scoreValue >= 0 && Number.isFinite(weightValue) && weightValue > 0;
  }

  function addAssignment() {
    const draft = parseAssignmentDraft();
    if (!draft.valid || !draft.value || !newAssignmentNameInput) {
      return;
    }

    if (editingAssignmentId === null) {
      assignments.push({
        id: assignmentIdCounter,
        ...draft.value
      });
      assignmentIdCounter += 1;
    } else {
      assignments = assignments.map((assignment) => {
        if (assignment.id !== editingAssignmentId) {
          return assignment;
        }
        return {
          ...assignment,
          ...draft.value
        };
      });
      clearEditingState();
    }

    clearAssignmentDraft();
    newAssignmentNameInput.focus();
    renderAssignments();
    if (isResultsStepActive()) {
      calculateAndRender();
    }
  }

  function canProceedToResults() {
    if (assignments.length === 0) {
      ValidationHelpers.showToast(
        container,
        __('Please add at least one assignment before calculating.', TEXT_DOMAIN),
        { type: 'error' }
      );
      return false;
    }

    const desiredGradeState = parseDesiredGrade({ markInvalid: true });
    if (!desiredGradeState.valid) {
      return false;
    }

    return true;
  }

  function calculateAndRender() {
    if (!resultPanel) {
      return;
    }

    ValidationHelpers.clearAllErrors(container);

    if (assignments.length === 0) {
      resultPanel.className = 'vareoncalc-panel-result vareoncalc-gradebook-report';
      ValidationHelpers.showResultError(resultPanel, __('Please add at least one assignment.', TEXT_DOMAIN));
      return;
    }

    const desiredGradeState = parseDesiredGrade({ markInvalid: true });
    if (!desiredGradeState.valid) {
      resultPanel.className = 'vareoncalc-panel-result vareoncalc-gradebook-report';
      ValidationHelpers.showResultError(resultPanel, desiredGradeState.message || __('Desired grade must be between 0 and 100.', TEXT_DOMAIN));
      return;
    }

    const totalWeight = getTotalWeight();
    const weightedSum = assignments.reduce((sum, assignment) => sum + (assignment.score * assignment.weight), 0);
    const currentGrade = totalWeight > 0 ? (weightedSum / totalWeight) : 0;
    const remainingWeight = Math.max(0, 100 - totalWeight);
    const isOverweight = totalWeight > 100 + OVERWEIGHT_TOLERANCE;
    const descriptor = getGradeDescriptor(currentGrade);

    renderReportCard(resultPanel, {
      currentGrade,
      letterGrade: descriptor.letter,
      gradeColor: descriptor.color,
      totalWeight,
      remainingWeight,
      desiredGrade: desiredGradeState.value,
      weightedSum,
      assignmentCount: assignments.length,
      isOverweight,
      entryMode
    });
    refreshTwoStepLayout();
  }

  function resetResults() {
    renderPlaceholder(resultPanel);
    refreshTwoStepLayout();
  }

  [newAssignmentNameInput, newAssignmentScoreInput, newAssignmentWeightInput].forEach((input, index, inputs) => {
    if (!input) {
      return;
    }
    input.addEventListener('keydown', (event) => {
      if (event.key === 'Enter') {
        event.preventDefault();
        if (index < inputs.length - 1) {
          inputs[index + 1]?.focus();
        } else {
          addAssignment();
        }
      } else if (event.key === 'Tab' && !event.shiftKey && index === inputs.length - 1) {
        if (hasValidDraftValues()) {
          event.preventDefault();
          addAssignment();
        }
      }
    });
  });

  addAssignmentBtn?.addEventListener('click', addAssignment);

  modeToggle?.addEventListener('click', (event) => {
    const target = event.target instanceof Element
      ? event.target.closest('button[data-gradebook-mode-option]')
      : null;
    if (!target) {
      return;
    }

    const nextMode = target.getAttribute('data-gradebook-mode-option') === 'points' ? 'points' : 'weight';
    if (nextMode === entryMode) {
      return;
    }

    entryMode = nextMode;
    updateModeToggleState();
    updateQuickAddCopy();

    if (editingAssignmentId !== null) {
      const editingAssignment = assignments.find((assignment) => assignment.id === editingAssignmentId);
      if (editingAssignment) {
        loadAssignmentIntoDraft(editingAssignment);
      } else {
        clearEditingState({ clearDraft: true });
      }
    } else {
      clearAssignmentDraft({ keepName: true });
    }

    renderAssignments();
    if (isResultsStepActive()) {
      calculateAndRender();
    }
  });

  addRemainingBtn?.addEventListener('click', () => {
    if (!newAssignmentNameInput || !newAssignmentWeightInput) {
      return;
    }
    const totalWeight = getTotalWeight();
    const remainingWeight = 100 - totalWeight;
    if (remainingWeight <= 0) {
      return;
    }
    if (!newAssignmentNameInput.value.trim()) {
      newAssignmentNameInput.value = __('Final', TEXT_DOMAIN);
    }
    newAssignmentWeightInput.value = formatWeight(remainingWeight);
    newAssignmentWeightInput.focus();
  });

  goalButtons.forEach((button) => {
    button.addEventListener('click', () => {
      if (!desiredGradeInput) {
        return;
      }
      const goalValue = parseFloat(button.dataset.goal || '');
      if (!Number.isFinite(goalValue)) {
        return;
      }
      desiredGradeInput.value = String(goalValue);
      ValidationHelpers.clearInvalid(desiredGradeInput);
      updateGoalCardState();
      if (isResultsStepActive()) {
        calculateAndRender();
      }
    });
  });

  desiredGradeInput?.addEventListener('input', () => {
    updateGoalCardState();
    if (isResultsStepActive()) {
      calculateAndRender();
    }
  });

  nextBtn?.addEventListener('click', (event) => {
    if (!canProceedToResults()) {
      event.preventDefault();
      return;
    }
    calculateAndRender();
  });

  settingsButton?.addEventListener('click', () => {
    setSettingsModalState(true);
  });
  settingsModalClose?.addEventListener('click', () => {
    setSettingsModalState(false, { returnFocus: true });
  });
  settingsModalDone?.addEventListener('click', () => {
    setSettingsModalState(false, { returnFocus: true });
    if (isResultsStepActive()) {
      calculateAndRender();
    }
  });
  settingsModalBackdrop?.addEventListener('click', () => {
    setSettingsModalState(false, { returnFocus: true });
  });

  document.addEventListener('keydown', (event) => {
    if (event.key !== 'Escape') {
      return;
    }
    if (!settingsModal || settingsModal.hasAttribute('hidden')) {
      return;
    }
    event.preventDefault();
    setSettingsModalState(false, { returnFocus: true });
  });

  container.addEventListener('keydown', (event) => {
    if (event.key !== 'Escape') {
      return;
    }
    if (editingAssignmentId === null || !settingsModal || !settingsModal.hasAttribute('hidden')) {
      return;
    }
    clearEditingState({ clearDraft: true });
    renderAssignments();
  });

  setSettingsModalState(false);
  updateModeToggleState();
  updateQuickAddCopy();
  updateAddAssignmentButtonState();
  renderAssignments();
  resetResults();
  updateGoalCardState();

  twoStepInstance = initCompactTwoStep(container, {
    canProceed: canProceedToResults
  });
  refreshTwoStepLayout();
}

function renderPlaceholder(panel) {
  if (!panel) {
    return;
  }
  panel.className = 'vareoncalc-panel-result vareoncalc-gradebook-report vareoncalc-gradebook-report--placeholder';
  panel.innerHTML = `
    <div class="gradebook-empty-state">
      <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
        <path d="M4 4h16v16H4z"></path>
        <path d="M8 9h8M8 13h8M8 17h5"></path>
      </svg>
      <p>${__('Add assignments in Step 1 to build your report card.', TEXT_DOMAIN)}</p>
    </div>
  `;
  applyThemedPanels(panel);
}

function renderReportCard(panel, data) {
  const {
    currentGrade,
    letterGrade,
    gradeColor,
    totalWeight,
    remainingWeight,
    desiredGrade,
    weightedSum,
    assignmentCount,
    isOverweight,
    entryMode
  } = data;
  const pointsMode = entryMode === 'points';

  const ringRadius = 66;
  const ringCircumference = 2 * Math.PI * ringRadius;
  const progressRatio = clamp(currentGrade / 100, 0, 1);
  const targetOffset = (1 - progressRatio) * ringCircumference;
  const meterNow = clamp(currentGrade, 0, 100);
  const meterText = sprintf(
    __('Current grade %s percent', TEXT_DOMAIN),
    currentGrade.toFixed(1)
  );

  let scenarioMarkup = '';
  if (isOverweight) {
    scenarioMarkup = `
      <div class="gradebook-scenario-card gradebook-scenario-card--notice">
        <div class="gradebook-scenario-card__title">${__('Extra credit or points detected', TEXT_DOMAIN)}</div>
        <div class="gradebook-scenario-card__message">
          ${pointsMode
      ? __('Total points exceed 100, so required-score scenarios are unavailable. Your current grade is shown above.', TEXT_DOMAIN)
      : __('Total weight exceeds 100, so required-score scenarios are unavailable. Your current grade is shown above.', TEXT_DOMAIN)}
        </div>
      </div>
    `;
  } else if (desiredGrade === null) {
    scenarioMarkup = `
      <div class="gradebook-scenario-card gradebook-scenario-card--prompt">
        <div class="gradebook-scenario-card__title">${__('Set a target grade', TEXT_DOMAIN)}</div>
        <div class="gradebook-scenario-card__message">
          ${__('Open Scenario Settings to enter a desired final grade and forecast your required score.', TEXT_DOMAIN)}
        </div>
      </div>
    `;
  } else if (remainingWeight <= 0) {
    scenarioMarkup = `
      <div class="gradebook-scenario-card gradebook-scenario-card--final">
        <div class="gradebook-scenario-card__title">${__('Final Assessment', TEXT_DOMAIN)}</div>
        <div class="gradebook-scenario-card__required-value">${currentGrade.toFixed(1)}%</div>
        <div class="gradebook-scenario-card__message">${__('All coursework has been graded.', TEXT_DOMAIN)}</div>
      </div>
    `;
  } else {
    const requiredWeightedSum = (desiredGrade * 100) - weightedSum;
    const requiredScore = requiredWeightedSum / remainingWeight;
    const displayScore = Math.max(0, requiredScore);

    let verdict = __('Doable', TEXT_DOMAIN);
    let verdictClass = 'gradebook-scenario-card__badge--easy';

    if (requiredScore > 100) {
      verdict = __('Requires Extra Credit', TEXT_DOMAIN);
      verdictClass = 'gradebook-scenario-card__badge--impossible';
    } else if (requiredScore < 0) {
      verdict = __('Already Achieved', TEXT_DOMAIN);
      verdictClass = 'gradebook-scenario-card__badge--achieved';
    } else if (requiredScore > 95) {
      verdict = __('Very Hard', TEXT_DOMAIN);
      verdictClass = 'gradebook-scenario-card__badge--hard';
    } else if (requiredScore > 85) {
      verdict = __('Challenging', TEXT_DOMAIN);
      verdictClass = 'gradebook-scenario-card__badge--moderate';
    }

    scenarioMarkup = `
      <div class="gradebook-scenario-card">
        <div class="gradebook-scenario-card__title">${sprintf(__('To Get a %s%%', TEXT_DOMAIN), desiredGrade)}</div>
        <div class="gradebook-scenario-card__required">
          <span class="gradebook-scenario-card__required-label">${__('You need to average', TEXT_DOMAIN)}</span>
          <span class="gradebook-scenario-card__required-value">${displayScore.toFixed(1)}%</span>
          <span class="gradebook-scenario-card__required-context">${pointsMode
      ? sprintf(__('on the remaining %s points', TEXT_DOMAIN), formatWeight(remainingWeight))
      : sprintf(__('on the remaining %s%%', TEXT_DOMAIN), formatWeight(remainingWeight))}</span>
        </div>
        <div class="gradebook-scenario-card__badge ${verdictClass}">
          <span class="gradebook-scenario-card__badge-text">${verdict}</span>
        </div>
      </div>
    `;
  }

  panel.className = 'vareoncalc-panel-result vareoncalc-gradebook-report';
  panel.innerHTML = `
    <div class="gradebook-report-hero">
      <div class="gradebook-ring-wrap">
        <div
          class="gradebook-ring"
          role="meter"
          aria-valuemin="0"
          aria-valuemax="100"
          aria-valuenow="${meterNow.toFixed(1)}"
          aria-valuetext="${escapeAttribute(meterText)}"
        >
          <svg viewBox="0 0 160 160" aria-hidden="true" focusable="false">
            <circle class="gradebook-ring__track" cx="80" cy="80" r="${ringRadius}"></circle>
            <circle
              class="gradebook-ring__progress"
              cx="80"
              cy="80"
              r="${ringRadius}"
              stroke="${gradeColor}"
              stroke-dasharray="${ringCircumference.toFixed(2)}"
              stroke-dashoffset="${ringCircumference.toFixed(2)}"
              data-target-offset="${targetOffset.toFixed(2)}"
            ></circle>
          </svg>
          <div class="gradebook-ring__center">
            <div class="gradebook-ring__value">${currentGrade.toFixed(1)}%</div>
            <div class="gradebook-ring__letter" style="color: ${gradeColor};">${letterGrade}</div>
          </div>
        </div>
      </div>

      <div class="gradebook-report-hero__summary">
        <div class="gradebook-report-hero__label">${__('Current Standing', TEXT_DOMAIN)}</div>
        <div class="gradebook-report-hero__headline">${getGradeStatus(currentGrade)}</div>
        <div class="gradebook-report-hero__stats">
          <span>${sprintf(__('Assignments: %s', TEXT_DOMAIN), String(assignmentCount))}</span>
          <span>${isOverweight
            ? pointsMode
              ? sprintf(__('Total points entered: %s', TEXT_DOMAIN), formatWeight(totalWeight))
              : sprintf(__('Total entered: %s', TEXT_DOMAIN), formatWeight(totalWeight))
            : pointsMode
              ? sprintf(__('Points entered: %s', TEXT_DOMAIN), formatWeight(totalWeight))
              : sprintf(__('Coursework entered: %s%%', TEXT_DOMAIN), formatWeight(totalWeight))}</span>
        </div>
      </div>
    </div>

    <div class="gradebook-report-metrics">
      <div class="gradebook-stat-card">
        <span class="gradebook-stat-card__label">${__('Current Grade', TEXT_DOMAIN)}</span>
        <span class="gradebook-stat-card__value">${currentGrade.toFixed(1)}%</span>
      </div>
      <div class="gradebook-stat-card">
        <span class="gradebook-stat-card__label">${pointsMode ? __('Entered Points', TEXT_DOMAIN) : __('Entered Weight', TEXT_DOMAIN)}</span>
        <span class="gradebook-stat-card__value">${isOverweight ? formatWeight(totalWeight) : pointsMode ? formatWeight(totalWeight) : `${formatWeight(totalWeight)}%`}</span>
      </div>
      <div class="gradebook-stat-card">
        <span class="gradebook-stat-card__label">${pointsMode ? __('Remaining Points', TEXT_DOMAIN) : __('Remaining Weight', TEXT_DOMAIN)}</span>
        <span class="gradebook-stat-card__value">${isOverweight ? __('N/A', TEXT_DOMAIN) : pointsMode ? formatWeight(Math.max(0, remainingWeight)) : `${formatWeight(Math.max(0, remainingWeight))}%`}</span>
      </div>
      <div class="gradebook-stat-card">
        <span class="gradebook-stat-card__label">${__('Target Grade', TEXT_DOMAIN)}</span>
        <span class="gradebook-stat-card__value">${desiredGrade === null ? '--' : `${desiredGrade.toFixed(1)}%`}</span>
      </div>
    </div>

    ${scenarioMarkup}
  `;

  const progressRing = panel.querySelector('.gradebook-ring__progress');
  if (progressRing) {
    const target = progressRing.getAttribute('data-target-offset');
    requestAnimationFrame(() => {
      progressRing.style.strokeDashoffset = target || '0';
    });
  }

  applyThemedPanels(panel);
}

function clamp(value, min, max) {
  return Math.min(Math.max(value, min), max);
}

function escapeAttribute(value) {
  return String(value)
    .replace(/&/g, '&amp;')
    .replace(/"/g, '&quot;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');
}
