/**
 * API 响应基础接口
 */
interface ApiResponse<T = any> {
  status: boolean | string;
  data: T;
  msg: string;
}

/**
 * 文件上传参数
 */
interface UploadParams {
  /** 文件路径或File对象 */
  filePath: string | File;
  /** 文件名，可选，默认会自动生成 */
  name?: string;
  /** 文件类型，可选，会根据文件扩展名自动判断 */
  type?: string;
  /** 上传进度回调 */
  onProgress?: (progress: number) => void;
}

/**
 * BowongAI SDK 类
 * 提供图像生成等 AI 功能的接口封装
 */
class FileApi {
  /** API 服务基础地址 */
  private readonly baseUrl = 'https://bowongai-test--text-video-agent-fastapi-app.modal.run';

  /**
   * H5版本的文件上传方法
   * @private
   */
  async upload(params: UploadParams): Promise<string> {
    const { filePath, name, type } = params;
    const url = `${this.baseUrl}/api/file/upload/s3`;

    try {
      // 自动生成文件名（如果未提供）
      const fileName = name || `upload_${Date.now()}.${this._getFileExtension(filePath)}`;
      // 自动判断文件类型（如果未提供）
      const fileType = type || this._getMimeType(filePath);

      console.log('开始上传文件 (H5模式):', {
        fileName,
        fileType,
      });

      // 创建FormData
      const formData = new FormData();

      // 在H5环境中，filePath可能是File对象或blob URL
      let file: File;
      if (filePath instanceof File) {
        file = filePath;
      } else if (typeof filePath === 'string') {
        // 如果是blob URL，转换为File对象
        const response = await fetch(filePath);
        const blob = await response.blob();
        file = new File([blob], fileName, { type: fileType });
      } else {
        throw new Error('不支持的文件类型');
      }

      formData.append('file', file);
      formData.append('filename', fileName);
      formData.append('type', fileType);

      // 使用fetch进行上传
      const uploadResponse = await fetch(url, {
        method: 'POST',
        body: formData,
        headers: {
          Accept: 'application/json',
        },
      });

      if (!uploadResponse.ok) {
        throw new Error(`HTTP ${uploadResponse.status}: 文件上传失败`);
      }

      const result: ApiResponse<string> = await uploadResponse.json();

      if (!result.status) {
        throw new Error(result.msg || '文件上传失败');
      }

      console.log('文件上传成功 (H5模式):', result.data);
      return result.data;
    } catch (error) {
      console.error('H5文件上传失败:', error);
      throw error;
    }
  }

  /**
   * 选择照片并上传 (H5版本)
   * 提供便捷的图片选择和上传功能，返回上传后的URL
   * @param options 选择图片的配置选项
   * @returns Promise<string> 返回上传后的文件URL
   */
  async chooseAndUploadImage(options?: {
    /** 最多可以选择的图片张数，默认为1 */
    count?: number;
    /** 所选的图片的尺寸，默认为 ['original', 'compressed'] */
    sizeType?: ('original' | 'compressed')[];
    /** 选择图片的来源，默认为 ['album', 'camera'] */
    sourceType?: ('album' | 'camera')[];
    /** 选择图片完成后的回调 */
    onImageSelected?: () => void;
    /** 上传进度回调 */
    onProgress?: (progress: number) => void;
  }): Promise<string> {
    const { onImageSelected, onProgress } = options || {};

    try {
      console.log('开始选择图片...');

      // H5版本使用文件选择器
      const file = await new Promise<File | null>(resolve => {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = 'image/*';
        input.style.display = 'none';

        document.body.appendChild(input);

        input.onchange = e => {
          const target = e.target as HTMLInputElement;
          const file = target.files?.[0] || null;
          document.body.removeChild(input);
          resolve(file);
        };

        input.click();
      });

      if (!file) {
        throw new Error('未选择图片');
      }

      console.log('图片选择结果:', file.name);

      // 选择图片完成后触发回调
      onImageSelected?.();

      // 上传图片
      console.log('开始上传图片:', file.name);

      const uploadUrl = await this.upload({
        filePath: file, // 传递File对象
        onProgress,
      });

      console.log('图片上传成功:', uploadUrl);
      return uploadUrl;
    } catch (error) {
      console.error('选择并上传图片失败:', error);
      throw error;
    }
  }

  /**
   * 根据文件路径或文件名获取文件扩展名
   * @private
   */
  private _getFileExtension(filePath: string | File): string {
    let fileName: string;
    if (filePath instanceof File) {
      fileName = filePath.name;
    } else {
      fileName = filePath;
    }
    const match = fileName.match(/\.([^.]+)$/);
    return match ? match[1] : 'jpg';
  }

  /**
   * 根据文件路径或文件对象获取 MIME 类型
   * @private
   */
  private _getMimeType(filePath: string | File): string {
    // 如果是File对象，优先使用其type属性
    if (filePath instanceof File && filePath.type) {
      return filePath.type;
    }

    const extension = this._getFileExtension(filePath).toLowerCase();
    const mimeTypes: Record<string, string> = {
      jpg: 'image/jpeg',
      jpeg: 'image/jpeg',
      png: 'image/png',
      gif: 'image/gif',
      webp: 'image/webp',
      mp4: 'video/mp4',
      mov: 'video/quicktime',
      avi: 'video/x-msvideo',
    };
    return mimeTypes[extension] || 'application/octet-stream';
  }

  /**
   * 查询任务状态
   * @param taskId 任务ID
   * @param retryCount 内部重试计数，外部调用不需要传入
   * @returns Promise<any> 返回任务状态信息
   */
  async getTaskStatus(taskId: string, retryCount: number = 0): Promise<string[]> {
    const url = `${this.baseUrl}/api/custom/task/status?task_id=${taskId}`;
    const maxRetries = 3;

    try {
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          Accept: 'application/json',
        },
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: 查询任务状态失败`);
      }

      const result = (await response.json()) as ApiResponse;
      if (!result.status) {
        throw new Error(result.msg || '查询任务状态失败');
      }

      if (result.status === 'running') {
        await new Promise(resolve => setTimeout(resolve, 1000 * 5));
        return this.getTaskStatus(taskId);
      }

      return result.data;
    } catch (error) {
      console.error(`查询任务状态失败 (第${retryCount + 1}次尝试):`, error);

      // 如果重试次数未达到最大值，等待5秒后重试
      if (retryCount < maxRetries) {
        console.log(`将在5秒后进行第${retryCount + 2}次重试...`);
        await new Promise(resolve => setTimeout(resolve, 5000));
        return this.getTaskStatus(taskId, retryCount + 1);
      }

      // 超过最大重试次数，抛出异常
      throw new Error(`查询任务状态失败，已重试${maxRetries}次: ${error instanceof Error ? error.message : String(error)}`);
    }
  }
}

export const fileApi = new FileApi();
