import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
import type {
  TvaiService,
  TvaiTask,
  TvaiConfig,
  VideoInfo,
  ImageInfo,
  GpuInfo,
  FfmpegInfo,
  UpscaleModel,
  QualityPreset,
  ImageFormat,
  TvaiEvents,
} from '../types/tvai';

/**
 * TVAI 服务实现
 */
export class TvaiServiceImpl implements TvaiService {
  private eventListeners: Map<string, Set<Function>> = new Map();

  constructor() {
    this.setupEventListeners();
  }

  /**
   * 设置事件监听器
   */
  private async setupEventListeners() {
    // 监听任务创建事件
    await listen<string>('tvai_task_created', (event) => {
      this.emitEvent('tvai_task_created', event.payload);
    });

    // 监听任务更新事件
    await listen<string>('tvai_task_updated', (event) => {
      this.emitEvent('tvai_task_updated', event.payload);
    });
  }

  /**
   * 添加事件监听器
   */
  public addEventListener<K extends keyof TvaiEvents>(
    event: K,
    listener: (data: TvaiEvents[K]) => void
  ): void {
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, new Set());
    }
    this.eventListeners.get(event)!.add(listener);
  }

  /**
   * 移除事件监听器
   */
  public removeEventListener<K extends keyof TvaiEvents>(
    event: K,
    listener: (data: TvaiEvents[K]) => void
  ): void {
    const listeners = this.eventListeners.get(event);
    if (listeners) {
      listeners.delete(listener);
    }
  }

  /**
   * 触发事件
   */
  private emitEvent<K extends keyof TvaiEvents>(event: K, data: TvaiEvents[K]): void {
    const listeners = this.eventListeners.get(event);
    if (listeners) {
      listeners.forEach(listener => listener(data));
    }
  }

  // 系统检测
  async detectTopazInstallation(): Promise<string | null> {
    return await invoke('detect_topaz_installation_command');
  }

  async detectGpuSupport(): Promise<GpuInfo> {
    return await invoke('detect_gpu_support_command');
  }

  async detectFfmpeg(): Promise<FfmpegInfo> {
    return await invoke('detect_ffmpeg_command');
  }

  // 配置
  async initializeTvaiConfig(config: TvaiConfig): Promise<void> {
    return await invoke('initialize_tvai_config', {
      topazPath: config.topaz_path,
      useGpu: config.use_gpu,
      tempDir: config.temp_dir,
    });
  }

  // 信息获取
  async getVideoInfo(videoPath: string): Promise<VideoInfo> {
    return await invoke('get_video_info_command', { videoPath });
  }

  async getImageInfo(imagePath: string): Promise<ImageInfo> {
    return await invoke('get_image_info_command', { imagePath });
  }

  async estimateProcessingTime(
    inputPath: string,
    scaleFactor?: number
  ): Promise<number> {
    return await invoke('estimate_processing_time_command', {
      inputPath,
      scaleFactor,
    });
  }

  // 快速处理
  async quickUpscaleVideo(
    inputPath: string,
    outputPath: string,
    scaleFactor: number,
    model?: UpscaleModel
  ): Promise<string> {
    return await invoke('quick_upscale_video_command', {
      inputPath,
      outputPath,
      scaleFactor,
      model,
    });
  }

  async quickUpscaleImage(
    inputPath: string,
    outputPath: string,
    scaleFactor: number
  ): Promise<string> {
    return await invoke('quick_upscale_image_command', {
      inputPath,
      outputPath,
      scaleFactor,
    });
  }

  // 快速插帧
  async quickInterpolateVideo(
    inputPath: string,
    outputPath: string,
    multiplier: number,
    inputFps: number
  ): Promise<string> {
    return await invoke('quick_interpolate_video_command', {
      inputPath,
      outputPath,
      multiplier,
      inputFps,
    });
  }

  // 自动增强
  async autoEnhanceVideo(inputPath: string, outputPath: string): Promise<string> {
    return await invoke('auto_enhance_video_command', {
      inputPath,
      outputPath,
    });
  }

  async autoEnhanceImage(inputPath: string, outputPath: string): Promise<string> {
    return await invoke('auto_enhance_image_command', {
      inputPath,
      outputPath,
    });
  }

  // 高级处理
  async upscaleVideoAdvanced(
    inputPath: string,
    outputPath: string,
    scaleFactor: number,
    model: UpscaleModel,
    compression: number,
    blend: number,
    qualityPreset: QualityPreset
  ): Promise<string> {
    return await invoke('upscale_video_advanced', {
      inputPath,
      outputPath,
      scaleFactor,
      model,
      compression,
      blend,
      qualityPreset,
    });
  }

  async upscaleImageAdvanced(
    inputPath: string,
    outputPath: string,
    scaleFactor: number,
    model: UpscaleModel,
    compression: number,
    blend: number,
    outputFormat: ImageFormat
  ): Promise<string> {
    return await invoke('upscale_image_advanced', {
      inputPath,
      outputPath,
      scaleFactor,
      model,
      compression,
      blend,
      outputFormat,
    });
  }

  // 任务管理
  async getTvaiTaskStatus(taskId: string): Promise<TvaiTask | null> {
    return await invoke('get_tvai_task_status', { taskId });
  }

  async getAllTvaiTasks(): Promise<TvaiTask[]> {
    return await invoke('get_all_tvai_tasks');
  }

  async cancelTvaiTask(taskId: string): Promise<void> {
    return await invoke('cancel_tvai_task', { taskId });
  }

  async cleanupCompletedTvaiTasks(): Promise<number> {
    return await invoke('cleanup_completed_tvai_tasks');
  }
}

// 创建单例实例
export const tvaiService = new TvaiServiceImpl();

// 导出便捷函数
export const {
  detectTopazInstallation,
  detectGpuSupport,
  detectFfmpeg,
  initializeTvaiConfig,
  getVideoInfo,
  getImageInfo,
  estimateProcessingTime,
  quickUpscaleVideo,
  quickUpscaleImage,
  autoEnhanceVideo,
  autoEnhanceImage,
  upscaleVideoAdvanced,
  upscaleImageAdvanced,
  getTvaiTaskStatus,
  getAllTvaiTasks,
  cancelTvaiTask,
  cleanupCompletedTvaiTasks,
} = tvaiService;

/**
 * 添加TVAI事件监听器的便捷函数
 */
export function addTvaiEventListener<K extends keyof TvaiEvents>(
  event: K,
  listener: (data: TvaiEvents[K]) => void
): void {
  tvaiService.addEventListener(event, listener);
}

/**
 * 移除TVAI事件监听器的便捷函数
 */
export function removeTvaiEventListener<K extends keyof TvaiEvents>(
  event: K,
  listener: (data: TvaiEvents[K]) => void
): void {
  tvaiService.removeEventListener(event, listener);
}
