/**
 * Collapsible Section Controls
 *
 * This module contains functions to control collapsible sections with font size controls.
 * Features include:
 * - Toggling between expanded and collapsed view
 * - Increasing and decreasing font size
 */

/**
 * Class representing a collapsible section with font size controls
 */
class CollapsibleSection {
  private readonly section: Element;
  private readonly content: HTMLElement;
  private readonly toggleTextElement: Element | null;
  private readonly toggleIconElement: HTMLElement | null;
  private readonly fontDisplayElement: Element | null;
  private readonly baseFontSize: number;
  private readonly initiallyCollapsed: boolean;

  /**
   * Create a new collapsible section
   * @param rootElement The root DOM element for this section
   */
  constructor(rootElement: Element) {
    this.section = rootElement;
    this.initiallyCollapsed = rootElement.hasAttribute(
      'data-initially-collapsed',
    );

    // Find and cache all necessary DOM elements
    const contentElement = rootElement.querySelector(
      '[data-collapsable="content"]',
    );
    if (!(contentElement instanceof HTMLElement)) {
      throw new Error(`Section is missing a content element`);
    }

    this.content = contentElement;

    // Get single elements instead of arrays
    this.toggleTextElement = rootElement.querySelector(
      '[data-collapsable="toggle-text"]',
    );

    const iconElement = rootElement.querySelector(
      '[data-collapsable="toggle-icon"]',
    );
    this.toggleIconElement =
      iconElement instanceof HTMLElement ? iconElement : null;

    this.fontDisplayElement = rootElement.querySelector(
      '[data-collapsable="font-display"]',
    );

    // Initialize font size info
    this.baseFontSize = parseFloat(
      window.getComputedStyle(this.content).fontSize,
    );
    this.updateFontSizeDisplay();
  }

  /**
   * Initialize event listeners for this section
   */
  initEventListeners(): void {
    // Setup handlers for all interactive elements
    this.section
      .querySelectorAll('[data-collapsable="toggle"]')
      .forEach((button) => {
        button.addEventListener('click', (e) => {
          e.preventDefault();
          this.toggle();
        });
      });

    this.section
      .querySelectorAll('[data-collapsable="decrease"]')
      .forEach((button) => {
        button.addEventListener('click', (e) => {
          e.preventDefault();
          this.decreaseFontSize();
        });
      });

    this.section
      .querySelectorAll('[data-collapsable="increase"]')
      .forEach((button) => {
        button.addEventListener('click', (e) => {
          e.preventDefault();
          this.increaseFontSize();
        });
      });
  }

  /**
   * Toggle between expanded and collapsed view
   */
  toggle(): void {
    // Determine current state from DOM
    const isCollapsed = this.content.classList.contains('line-clamp-6');

    // Toggle line-clamp class
    this.content.classList.toggle('line-clamp-6');

    // Update toggle text
    if (this.toggleTextElement) {
      this.toggleTextElement.textContent = isCollapsed
        ? 'Show Less'
        : 'Show More';
    }

    // Update toggle icon
    if (this.toggleIconElement) {
      this.toggleIconElement.style.transform = isCollapsed
        ? 'rotate(180deg)'
        : 'rotate(0deg)';
    }
  }

  /**
   * Adjust font size of content within min/max bounds
   */
  adjustFontSize(delta: number, min = 12, max = 22): void {
    const currentSize = parseFloat(
      window.getComputedStyle(this.content).fontSize,
    );
    const newSize = Math.min(Math.max(currentSize + delta, min), max);

    this.content.style.fontSize = `${newSize}px`;
    this.updateFontSizeDisplay();
  }

  /**
   * Increase font size (max 22px)
   */
  increaseFontSize(): void {
    this.adjustFontSize(2);
  }

  /**
   * Decrease font size (min 12px)
   */
  decreaseFontSize(): void {
    this.adjustFontSize(-2);
  }

  /**
   * Update the font size percentage display
   */
  updateFontSizeDisplay(): void {
    if (!this.fontDisplayElement) return;

    const currentSize = parseFloat(
      window.getComputedStyle(this.content).fontSize,
    );
    const percentage = Math.round((currentSize / this.baseFontSize) * 100);

    this.fontDisplayElement.textContent = `${percentage}%`;
  }
}

/**
 * Initialize all collapsible sections on the page
 */
export function initCollapsibleSections(): void {
  document
    .querySelectorAll('[data-collapsable="root"]')
    .forEach((sectionElement) => {
      try {
        // Create a new section instance
        const section = new CollapsibleSection(sectionElement);

        // Set up event handlers
        section.initEventListeners();
      } catch (error) {
        console.error('Failed to initialize section:', error);
      }
    });
}
