// @ts-nocheck

const _AppBase =
  typeof foundry !== 'undefined' &&
  foundry.applications?.api?.HandlebarsApplicationMixin &&
  foundry.applications?.api?.ApplicationV2
    ? foundry.applications.api.HandlebarsApplicationMixin(
        foundry.applications.api.ApplicationV2
      )
    : class _FallbackApp {
        static DEFAULT_OPTIONS = {};
        static PARTS = {};
        constructor(options = {}) { this.options = options; this.position = {}; }
        get rendered() { return this._rendered ?? false; }
        set rendered(v) { this._rendered = v; }
        get element() { return this._element ?? null; }
        set element(v) { this._element = v; }
        async render() { this._rendered = true; }
        async close() { this._rendered = false; }
        async _prepareContext() { return {}; }
        _onRender() {}
        _onClose() {}
        _onPosition() {}
        setPosition(p) { Object.assign(this.position, p); }
      };

/**
 * Individual floating camera window for the freeform layout.
 * One instance per participant, fully resizable and draggable.
 */
export class FreeformCameraWindow extends _AppBase {
  static DEFAULT_OPTIONS = {
    classes: ['scrying-pool', 'freeform-camera'],
    window: {
      icon: 'fas fa-video',
      resizable: true,
      controls: [
        { action: 'spotlight', icon: 'fas fa-star', title: 'SCRYING_POOL.Freeform.spotlight' },
        { action: 'hide', icon: 'fas fa-eye-slash', title: 'SCRYING_POOL.Freeform.hide' },
      ],
    },
    position: { width: 320, height: 300 },
  };

  static PARTS = {
    body: {
      template: 'modules/scrying-pool/templates/freeform-camera.hbs',
    },
  };

  /**
   * @param {object} params
   * @param {string} params.userId
   * @param {object} params.adapter - FoundryAdapter instance
   * @param {object} params.manager - FreeformLayoutManager instance
   * @param {{left:number, top:number, width:number, height:number}} params.position
   */
  constructor({ userId, adapter, manager, position }) {
    const user = adapter.users.get(userId);
    super({
      position: { ...position },
      window: { title: user?.name ?? userId },
    });
    this._userId = userId;
    this._adapter = adapter;
    this._manager = manager;
    this._videoElement = null;
    this._volume = 1.0;
    this._isSpotlight = false;
  }

  /** @returns {string} */
  get userId() { return this._userId; }

  /** @param {boolean} val */
  set spotlight(val) {
    this._isSpotlight = val;
    if (this.element) {
      this.element.classList.toggle('is-spotlight', val);
    }
  }

  /** @returns {boolean} */
  get spotlight() { return this._isSpotlight; }

  /** @inheritdoc */
  async _prepareContext() {
    const user = this._adapter.users.get(this._userId);
    const stream = this._adapter.webrtc?.getMediaStreamForUser?.(this._userId);
    const hasAudio = stream?.getAudioTracks()?.length > 0;
    const audioMuted = hasAudio
      ? stream.getAudioTracks().every(t => !t.enabled)
      : true;

    return {
      userId: this._userId,
      userName: user?.name ?? this._userId,
      hasAudio,
      audioMuted,
      volume: this._volume,
    };
  }

  /** @inheritdoc */
  _onRender(context, options) {
    super._onRender?.(context, options);
    this._attachVideo();

    if (this._isSpotlight) {
      this.element?.classList.add('is-spotlight');
    }

    const volumeSlider = this.element?.querySelector('.freeform-camera__volume');
    if (volumeSlider) {
      volumeSlider.value = String(this._volume);
      volumeSlider.addEventListener('input', (e) => {
        this._volume = parseFloat(e.target.value);
        if (this._videoElement) {
          this._videoElement.volume = this._volume;
        }
      });
    }

    const micBtn = this.element?.querySelector('[data-action="toggle-mic"]');
    if (micBtn) {
      micBtn.addEventListener('click', () => this._toggleMic());
    }

    const videoContainer = this.element?.querySelector('.freeform-camera__video-container');
    if (videoContainer) {
      videoContainer.addEventListener('dblclick', (e) => {
        e.stopPropagation();
        this._manager?.openSettings?.();
      });
    }
  }

  /**
   * Attaches the user's webcam stream as a <video> element.
   * Called from _onRender.
   */
  _attachVideo() {
    if (!this._adapter?.webrtc?.getMediaStreamForUser) return;
    if (!this.element) return;

    const container = this.element.querySelector('.freeform-camera__video-container');
    if (!container) return;

    const existing = container.querySelector('video');
    if (existing) existing.remove();

    const stream = this._adapter.webrtc.getMediaStreamForUser(this._userId);
    if (!stream) return;

    const video = document.createElement('video');
    video.srcObject = stream;
    video.autoplay = true;
    video.playsInline = true;
    video.muted = this._adapter.users.current?.()?.id === this._userId;
    video.className = 'freeform-camera__video-element';

    video.addEventListener('error', () => {
      console.warn('[ScryingPool] Freeform video error for user:', this._userId);
    });

    container.appendChild(video);
    this._videoElement = video;
    video.volume = this._volume;
  }

  /**
   * Detaches and cleans up the video element.
   */
  _detachVideo() {
    if (this._videoElement) {
      this._videoElement.pause();
      this._videoElement.srcObject = null;
      this._videoElement.remove();
      this._videoElement = null;
    }
    const container = this.element?.querySelector('.freeform-camera__video-container');
    if (container) {
      const els = container.querySelectorAll('video');
      els.forEach(v => { v.pause(); v.srcObject = null; v.remove(); });
    }
  }

  /**
   * Toggles the local microphone mute state for this participant's stream.
   */
  _toggleMic() {
    const stream = this._adapter.webrtc?.getMediaStreamForUser?.(this._userId);
    if (!stream) return;
    const tracks = stream.getAudioTracks();
    if (tracks.length === 0) return;
    const allMuted = tracks.every(t => !t.enabled);
    tracks.forEach(t => { t.enabled = allMuted; });
    const btn = this.element?.querySelector('[data-action="toggle-mic"] i');
    if (btn) {
      btn.className = allMuted ? 'fas fa-microphone' : 'fas fa-microphone-slash';
    }
  }

  /** @inheritdoc */
  _onClickWindowControl(event) {
    const btn = event.currentTarget;
    const action = btn.dataset.action;
    if (action === 'spotlight') {
      this._manager.setSpotlight(this._userId);
    } else if (action === 'hide') {
      this._hideParticipant();
    }
  }

  /**
   * Hides this participant from the table via the manager.
   * @returns {Promise<void>}
   */
  async _hideParticipant() {
    await this._manager?.hideParticipant(this._userId);
  }

  /** @inheritdoc */
  _onPosition(position) {
    super._onPosition?.(position);
    this._manager?._scheduleSave();
  }

  /** @inheritdoc */
  async _onClose(options) {
    this._detachVideo();
    if (!options?._fromManager) {
      await this._hideParticipant();
    }
    await super._onClose?.(options);
  }

  /**
   * Synchronously removes this window from the DOM.
   * Bypasses the async ApplicationV2 close lifecycle for reliable cleanup.
   * Does NOT hide the participant — used by FreeformLayoutManager on layout switch.
   */
  removeDOM() {
    this._detachVideo();
    if (this.element) {
      this.element.remove();
    }
    this._rendered = false;
  }
}
