/**
 * @file 摄像头流管理器
 * @description 管理摄像头视频流的创建、销毁、暂停和恢复
 * @module core/camera-stream-manager
 */

import { EventEmitter } from './event-emitter';
import { Logger } from './logger';
import { CameraAccessError } from './errors';
import { Disposable } from '../utils/resource-manager';

/**
 * 摄像头流状态
 */
export enum StreamState {
  /** 空闲 */
  IDLE = 'idle',
  /** 启动中 */
  STARTING = 'starting',
  /** 活动中 */
  ACTIVE = 'active',
  /** 已暂停 */
  PAUSED = 'paused',
  /** 已停止 */
  STOPPED = 'stopped',
  /** 错误 */
  ERROR = 'error'
}

/**
 * 摄像头流事件
 */
export enum CameraStreamEvent {
  /** 流启动 */
  START = 'stream:start',
  /** 流停止 */
  STOP = 'stream:stop',
  /** 流暂停 */
  PAUSE = 'stream:pause',
  /** 流恢复 */
  RESUME = 'stream:resume',
  /** 流错误 */
  ERROR = 'stream:error',
  /** 轨道结束 */
  TRACK_ENDED = 'stream:track:ended',
  /** 分辨率变化 */
  RESOLUTION_CHANGE = 'stream:resolution:change'
}

/**
 * 摄像头流管理器接口
 */
export interface ICameraStreamManager {
  /** 获取媒体流 */
  getStream(): MediaStream | null;
  /** 是否活动 */
  isActive(): boolean;
  /** 获取当前状态 */
  getState(): StreamState;
  /** 释放资源 */
  dispose(): Promise<void>;
}

/**
 * 摄像头流管理器
 * 负责摄像头视频流的生命周期管理
 */
export class CameraStreamManager extends EventEmitter implements ICameraStreamManager, Disposable {
  /** 日志记录器 */
  private readonly logger: Logger;
  /** 媒体流 */
  private mediaStream: MediaStream | null = null;
  /** 流状态 */
  private state: StreamState = StreamState.IDLE;
  /** 视频轨道 */
  private videoTrack: MediaStreamTrack | null = null;
  /** 音频轨道 */
  private audioTrack: MediaStreamTrack | null = null;
  /** 视频元素引用 */
  private videoElement: HTMLVideoElement | null = null;
  /** 是否已暂停（用于pause/resume） */
  private isPaused: boolean = false;

  /**
   * 构造函数
   */
  constructor() {
    super();
    this.logger = Logger.getInstance();
  }

  /**
   * 获取媒体流
   */
  getStream(): MediaStream | null {
    return this.mediaStream;
  }

  /**
   * 是否活动
   */
  isActive(): boolean {
    return this.state === StreamState.ACTIVE && !this.isPaused;
  }

  /**
   * 获取当前状态
   */
  getState(): StreamState {
    return this.state;
  }

  /**
   * 启动摄像头流
   * @param constraints 媒体约束
   * @param videoElement 可选的视频元素
   */
  async start(
    constraints: MediaStreamConstraints,
    videoElement?: HTMLVideoElement | null
  ): Promise<MediaStream> {
    if (this.state === StreamState.ACTIVE && this.mediaStream) {
      this.logger.debug('CameraStreamManager', 'Stream already active');
      return this.mediaStream;
    }

    this.state = StreamState.STARTING;
    this.logger.debug('CameraStreamManager', `Requesting camera access: ${JSON.stringify(constraints)}`);

    try {
      // 停止旧流
      this.stopStreamOnly();

      // 获取新流
      const stream = await navigator.mediaDevices.getUserMedia(constraints);
      this.mediaStream = stream;

      // 获取轨道
      const tracks = stream.getTracks();
      this.videoTrack = tracks.find(t => t.kind === 'video') || null;
      this.audioTrack = tracks.find(t => t.kind === 'audio') || null;

      // 监听轨道结束事件
      if (this.videoTrack) {
        this.videoTrack.onended = this.handleTrackEnded.bind(this);
      }

      // 保存视频元素引用
      this.videoElement = videoElement || null;

      // 将流连接到视频元素
      if (this.videoElement) {
        this.videoElement.srcObject = stream;
      }

      this.state = StreamState.ACTIVE;
      this.isPaused = false;

      this.emit(CameraStreamEvent.START, {
        stream,
        deviceId: this.videoTrack?.getSettings().deviceId,
        settings: this.videoTrack?.getSettings()
      });

      return stream;
    } catch (error) {
      this.state = StreamState.ERROR;
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.logger.error('CameraStreamManager', `Failed to start stream: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage));

      const cameraError = new CameraAccessError(errorMessage);
      this.emit(CameraStreamEvent.ERROR, { error: cameraError });
      throw cameraError;
    }
  }

  /**
   * 停止摄像头流
   */
  stop(): void {
    if (this.state !== StreamState.ACTIVE && this.state !== StreamState.PAUSED) {
      return;
    }

    // 停止所有轨道
    this.stopStreamOnly();

    // 断开视频元素连接
    if (this.videoElement) {
      this.videoElement.pause();
      this.videoElement.srcObject = null;
      this.videoElement = null;
    }

    this.state = StreamState.STOPPED;
    this.isPaused = false;

    this.emit(CameraStreamEvent.STOP);
  }

  /**
   * 暂停摄像头流
   */
  pause(): void {
    if (this.state !== StreamState.ACTIVE || this.isPaused) {
      return;
    }

    // 暂停视频元素
    if (this.videoElement) {
      this.videoElement.pause();
    }

    this.isPaused = true;
    this.state = StreamState.PAUSED;

    this.emit(CameraStreamEvent.PAUSE);
  }

  /**
   * 恢复摄像头流
   * @returns 是否成功恢复
   */
  async resume(): Promise<boolean> {
    if (this.state !== StreamState.PAUSED || !this.isPaused) {
      return false;
    }

    if (this.videoElement && this.videoElement.paused && this.mediaStream) {
      try {
        await this.videoElement.play();
        this.isPaused = false;
        this.state = StreamState.ACTIVE;

        this.emit(CameraStreamEvent.RESUME);
        return true;
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger.error('CameraStreamManager', `Failed to resume stream: ${errorMessage}`, error instanceof Error ? error : new Error(errorMessage));
        return false;
      }
    }

    return false;
  }

  /**
   * 连接到视频元素
   * @param videoElement 视频元素
   */
  attachToVideoElement(videoElement: HTMLVideoElement): void {
    this.videoElement = videoElement;

    if (this.mediaStream) {
      videoElement.srcObject = this.mediaStream;
    }
  }

  /**
   * 断开视频元素连接
   */
  detachVideoElement(): void {
    if (this.videoElement) {
      this.videoElement.pause();
      this.videoElement.srcObject = null;
      this.videoElement = null;
    }
  }

  /**
   * 获取视频轨道设置
   */
  getVideoSettings(): MediaTrackSettings | null {
    return this.videoTrack?.getSettings() || null;
  }

  /**
   * 获取视频轨道
   */
  getVideoTrack(): MediaStreamTrack | null {
    return this.videoTrack;
  }

  /**
   * 释放资源
   */
  async dispose(): Promise<void> {
    this.stop();

    this.videoTrack = null;
    this.audioTrack = null;
    this.mediaStream = null;
    this.state = StreamState.IDLE;

    this.logger.debug('CameraStreamManager', 'CameraStreamManager resources disposed');
  }

  /**
   * 停止媒体流（仅停止轨道不断开视频元素）
   */
  private stopStreamOnly(): void {
    if (this.mediaStream) {
      this.mediaStream.getTracks().forEach(track => track.stop());
      this.mediaStream = null;
    }

    this.videoTrack = null;
    this.audioTrack = null;
  }

  /**
   * 处理轨道结束事件
   */
  private handleTrackEnded(): void {
    this.logger.debug('CameraStreamManager', 'Camera track ended');
    this.emit(CameraStreamEvent.TRACK_ENDED);
  }
}
