/**
 * ScenePresetPanel — Per-scene auto-apply configuration UI.
 *
 * Owns: Toggle, preset selector, pre-delay slider for per-scene auto-apply settings.
 * Embedded in DirectorsBoard as collapsible drawer/tab.
 *
 * Import rule: may import from src/core/, src/contracts/, src/utils/ ONLY.
 * Constructors are side-effect free — call init() from DirectorsBoard.
 *
 * Story 3.2: Scene Auto-Apply & ConfirmationBar
 *
 * @module ui/gm/ScenePresetPanel
 */

/**
 * Per-scene auto-apply configuration panel.
 * Allows GM to configure which preset (if any) auto-applies when a scene activates.
 */
export class ScenePresetPanel {
  /**
   * @param {import('../../foundry/FoundryAdapter.js').FoundryAdapter} adapter
   *   Injected FoundryAdapter surface.
   * @param {import('../../core/ScenePresetManager.js').ScenePresetManager} scenePresetManager
   *   Injected ScenePresetManager for preset operations.
   */
  constructor(adapter, scenePresetManager) {
    this._adapter = adapter;
    this._scenePresetManager = scenePresetManager;
    
    // State
    /** @type {HTMLElement|null} */
    this._element = null;
    /** @type {boolean} */
    this._isOpen = false;
    /** @type {object|null} */
    this._currentScene = null;
    /** @type {Function|null} */
    this._clickHandler = null;
    /** @type {Function|null} */
    this._changeHandler = null;
    /** @type {Function|null} */
    this._inputHandler = null;
    
    // Constants
    /** @type {number} Maximum pre-delay in milliseconds */
    this._MAX_PREDELAY = 5000;
    /** @type {number} Minimum pre-delay in milliseconds */
    this._MIN_PREDELAY = 0;
  }

  /**
   * Initializes the panel. Creates DOM element and sets up event listeners.
   * Called from DirectorsBoard constructor.
   */
  init() {
    this._createElement();
    this._setupEventListeners();
    this._refresh();
  }

  /**
   * Creates the panel DOM element.
   * @private
   */
  _createElement() {
    this._element = document.createElement('div');
    this._element.className = 'directors-board__preset-panel';
    this._element.setAttribute('role', 'region');
    this._element.setAttribute('aria-label', this._adapter.i18n.localize('scrying-pool.scenePresetPanel.title'));
    this._element.setAttribute('aria-expanded', 'false');
    
    // Initially hidden
    this._element.style.display = 'none';
  }

  /**
   * Returns the panel DOM element.
   * @returns {HTMLElement|null}
   */
  get element() {
    return this._element;
  }

  /**
   * Toggles the panel visibility.
   */
  toggle() {
    if (this._isOpen) {
      this.close();
    } else {
      this.open();
    }
  }

  /**
   * Opens the panel and refreshes its content.
   */
  open() {
    if (!this._element) return;
    
    this._isOpen = true;
    this._element.style.display = 'block';
    this._element.setAttribute('aria-expanded', 'true');
    this._refresh();
  }

  /**
   * Closes the panel.
   */
  close() {
    if (!this._element) return;
    
    this._isOpen = false;
    this._element.style.display = 'none';
    this._element.setAttribute('aria-expanded', 'false');
  }

  /**
   * Refreshes the panel content with current scene data.
   * @private
   */
  async _refresh() {
    if (!this._element) return;
    
    const currentScene = this._adapter.scenes.current?.();
    if (!currentScene) {
      this._element.innerHTML = this._buildEmptyHtml();
      return;
    }
    
    this._currentScene = currentScene;
    
    // Get current auto-apply config
    const autoApplyConfig = this._scenePresetManager._getAutoApplyConfig(
      this._scenePresetManager._getSceneFlagData(currentScene)
    );
    
    // Get available presets
    const presets = this._scenePresetManager.list();
    
    this._element.innerHTML = this._buildHtml({
      enabled: autoApplyConfig.enabled,
      presetName: autoApplyConfig.presetName,
      preDelay: autoApplyConfig.preDelay,
      presets,
    });
    
    // Update toggle state
    const toggle = this._element.querySelector('[data-action="toggle-auto-apply"]');
    if (toggle) {
      toggle.setAttribute('aria-pressed', String(autoApplyConfig.enabled));
    }
  }

  /**
   * Builds the HTML for the panel when no scene is active.
   * @returns {string}
   * @private
   */
  _buildEmptyHtml() {
    const message = this._adapter.i18n.localize('scrying-pool.scenePresetPanel.noScene');
    return `
      <div class="directors-board__preset-panel-header">
        <h3 class="directors-board__preset-panel-title">
          ${this._escapeHtml(this._adapter.i18n.localize('scrying-pool.scenePresetPanel.title'))}
        </h3>
      </div>
      <p class="directors-board__preset-panel-message">${this._escapeHtml(message)}</p>
    `;
  }

  /**
   * Builds the HTML for the panel.
   * @param {object} context - Panel context.
   * @param {boolean} context.enabled - Whether auto-apply is enabled.
   * @param {string|null} context.presetName - Selected preset name.
   * @param {number} context.preDelay - Pre-delay in milliseconds.
   * @param {Array<object>} context.presets - Available presets.
   * @returns {string}
   * @private
   */
  _buildHtml(context) {
    const { enabled, presetName, preDelay, presets } = context;
    const localize = this._adapter.i18n.localize;
    
    // Build preset options
    const presetOptions = presets
      .map(preset => `
        <option value="${this._escapeHtml(preset.name)}" ${preset.name === presetName ? 'selected' : ''}>
          ${this._escapeHtml(preset.name)}
        </option>
      `)
      .join('');
    
    // Add default option
    const defaultOption = `
      <option value="" ${!presetName ? 'selected' : ''}>
        ${this._escapeHtml(localize('scrying-pool.scenePresetPanel.selectPreset'))}
      </option>
    `;
    
    return `
      <div class="directors-board__preset-panel-header">
        <h3 class="directors-board__preset-panel-title">
          ${this._escapeHtml(localize('scrying-pool.scenePresetPanel.title'))}
        </h3>
      </div>
      
      <div class="directors-board__preset-panel-body">
        <div class="directors-board__preset-panel-row">
          <label class="directors-board__preset-panel-label">
            <input type="checkbox" 
                   class="directors-board__preset-panel-toggle"
                   data-action="toggle-auto-apply"
                   ${enabled ? 'checked' : ''}
                   role="switch"
                   aria-label="${this._escapeHtml(localize('scrying-pool.scenePresetPanel.enableAutoApply'))}">
            ${this._escapeHtml(localize('scrying-pool.scenePresetPanel.enableAutoApply'))}
          </label>
        </div>
        
        <div class="directors-board__preset-panel-row">
          <label class="directors-board__preset-panel-label">
            ${this._escapeHtml(localize('scrying-pool.scenePresetPanel.preset'))}
            <select class="directors-board__preset-panel-select"
                    data-action="select-preset"
                    ${!presets.length ? 'disabled' : ''}
                    aria-label="${this._escapeHtml(localize('scrying-pool.scenePresetPanel.selectPreset'))}">
              ${defaultOption}
              ${presetOptions}
            </select>
          </label>
        </div>
        
        <div class="directors-board__preset-panel-row">
          <label class="directors-board__preset-panel-label">
            ${this._escapeHtml(localize('scrying-pool.scenePresetPanel.preDelay'))}
            <span class="directors-board__preset-panel-delay-value">${preDelay}ms</span>
            <input type="range" 
                   class="directors-board__preset-panel-slider"
                   data-action="change-delay"
                   min="${this._MIN_PREDELAY}" 
                   max="${this._MAX_PREDELAY}" 
                   value="${preDelay}"
                   step="100"
                   aria-label="${this._escapeHtml(localize('scrying-pool.scenePresetPanel.preDelay'))}"
                   aria-valuemin="${this._MIN_PREDELAY}"
                   aria-valuemax="${this._MAX_PREDELAY}"
                   aria-valuenow="${preDelay}">
          </label>
        </div>
        
        <div class="directors-board__preset-panel-row directors-board__preset-panel-row--hint">
          <span>${this._escapeHtml(localize('scrying-pool.scenePresetPanel.globalSettingsHint'))}</span>
        </div>
      </div>
    `;
  }

  /**
   * Sets up event listeners for the panel.
   * @private
   */
  _setupEventListeners() {
    if (!this._element) return;
    
    // Store bound handlers
    this._clickHandler = (event) => {
      const target = event.target.closest?.('[data-action]');
      if (!target) return;
      
      const action = target.getAttribute('data-action');
      switch (action) {
        case 'toggle-auto-apply':
          this._onToggleAutoApply(target);
          break;
        case 'select-preset':
          this._onPresetSelected(target);
          break;
        case 'change-delay':
          // Deliberate fallthrough - handled by input handler
          break;
      }
    };
    
    this._inputHandler = (event) => {
      const target = event.target.closest?.('[data-action="change-delay"]');
      if (!target) return;
      this._onDelayChanged(target);
    };
    
    this._element.addEventListener('click', this._clickHandler);
    this._element.addEventListener('input', this._inputHandler);
  }

  /**
   * Removes event listeners.
   * @private
   */
  _removeEventListeners() {
    if (!this._element) return;
    
    if (this._clickHandler) {
      this._element.removeEventListener('click', this._clickHandler);
      this._clickHandler = null;
    }
    if (this._inputHandler) {
      this._element.removeEventListener('input', this._inputHandler);
      this._inputHandler = null;
    }
  }

  /**
   * Handles the auto-apply toggle change.
   * @param {HTMLElement} target - The toggle element.
   * @private
   */
  async _onToggleAutoApply(target) {
    const isChecked = target instanceof HTMLInputElement ? target.checked : false;
    const currentScene = this._adapter.scenes.current?.();
    if (!currentScene) return;
    
    try {
      // Get current config
      const flagData = this._scenePresetManager._getSceneFlagData(currentScene);
      const autoApplyConfig = this._scenePresetManager._getAutoApplyConfig(flagData);
      
      // Update and save
      await this._scenePresetManager.configureAutoApply(currentScene, {
        enabled: isChecked,
        presetName: autoApplyConfig.presetName,
        preDelay: autoApplyConfig.preDelay,
      });
      
      // Update UI state
      target.setAttribute('aria-pressed', String(isChecked));
      
      // Notify
      this._adapter.notifications.info(
        isChecked
          ? this._adapter.i18n.localize('scrying-pool.scenePresetPanel.notifications.enabled')
          : this._adapter.i18n.localize('scrying-pool.scenePresetPanel.notifications.disabled')
      );
    } catch (err) {
      console.error('[ScryingPool] ScenePresetPanel: failed to toggle auto-apply', err);
      // Revert toggle state
      target.checked = !isChecked;
    }
  }

  /**
   * Handles preset selection change.
   * @param {HTMLElement} target - The select element.
   * @private
   */
  async _onPresetSelected(target) {
    const presetName = target.value;
    const currentScene = this._adapter.scenes.current?.();
    if (!currentScene) return;
    
    try {
      // Get current config
      const flagData = this._scenePresetManager._getSceneFlagData(currentScene);
      const autoApplyConfig = this._scenePresetManager._getAutoApplyConfig(flagData);
      
      // Update and save
      await this._scenePresetManager.configureAutoApply(currentScene, {
        enabled: autoApplyConfig.enabled,
        presetName: presetName || null,
        preDelay: autoApplyConfig.preDelay,
      });
      
      // Notify
      if (presetName) {
        this._adapter.notifications.info(
          this._adapter.i18n.localize('scrying-pool.scenePresetPanel.notifications.presetSelected')
            .replace('{name}', presetName)
        );
      }
    } catch (err) {
      console.error('[ScryingPool] ScenePresetPanel: failed to select preset', err);
    }
  }

  /**
   * Handles pre-delay slider change.
   * @param {HTMLElement} target - The slider element.
   * @private
   */
  async _onDelayChanged(target) {
    const preDelay = parseInt(target.value, 10) || 0;
    const currentScene = this._adapter.scenes.current?.();
    if (!currentScene) return;
    
    // Update displayed value
    const valueDisplay = this._element?.querySelector('.directors-board__preset-panel-delay-value');
    if (valueDisplay) {
      valueDisplay.textContent = `${preDelay}ms`;
      valueDisplay.setAttribute('aria-valuenow', String(preDelay));
    }
    
    try {
      // Get current config
      const flagData = this._scenePresetManager._getSceneFlagData(currentScene);
      const autoApplyConfig = this._scenePresetManager._getAutoApplyConfig(flagData);
      
      // Update and save
      await this._scenePresetManager.configureAutoApply(currentScene, {
        enabled: autoApplyConfig.enabled,
        presetName: autoApplyConfig.presetName,
        preDelay,
      });
    } catch (err) {
      console.error('[ScryingPool] ScenePresetPanel: failed to change delay', err);
    }
  }

  /**
   * Cleans up the panel.
   */
  teardown() {
    this._removeEventListeners();
    this.close();
    
    if (this._element && this._element.parentNode) {
      this._element.parentNode.removeChild(this._element);
    }
    this._element = null;
    this._isOpen = false;
    this._currentScene = null;
  }

  /**
   * Escapes HTML special characters to prevent XSS.
   * @param {string} str - String to escape.
   * @returns {string} Escaped string.
   * @private
   */
  _escapeHtml(str) {
    if (!str || typeof str !== 'string') {
      return '';
    }
    return str
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#x27;');
  }
}
