/**
 * 文件上传服务
 * 处理与 file-service 的所有文件相关 API 调用
 */

export interface FileInfo {
  id: string;
  originalName: string;
  mimeType: string;
  type: 'image' | 'document' | 'audio' | 'video' | 'other';
  size: number;
  status: 'uploading' | 'processing' | 'ready' | 'failed' | 'deleted';
  thumbnailUrl?: string;
  downloadUrl?: string;
  createdAt: string;
}

export interface PresignedUrlResponse {
  uploadUrl: string;
  fileId: string;
  objectName: string;
  expiresIn: number;
}

export interface UploadProgress {
  fileId: string;
  fileName: string;
  progress: number;
  status: 'uploading' | 'success' | 'error';
  error?: string;
}

// 允许上传的文件类型
export const ALLOWED_FILE_TYPES = {
  image: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'],
  document: [
    'application/pdf',
    'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'application/vnd.ms-excel',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'text/plain',
    'text/csv',
    'text/markdown',
  ],
};

export const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB
export const MAX_DIRECT_UPLOAD_SIZE = 10 * 1024 * 1024; // 10MB

/**
 * 验证文件类型和大小
 */
export function validateFile(file: File): { valid: boolean; error?: string } {
  const allAllowedTypes = [...ALLOWED_FILE_TYPES.image, ...ALLOWED_FILE_TYPES.document];

  if (!allAllowedTypes.includes(file.type)) {
    return {
      valid: false,
      error: `不支持的文件类型: ${file.type}。支持的类型: 图片 (JPEG, PNG, GIF, WebP, SVG) 和文档 (PDF, Word, Excel, 文本)`,
    };
  }

  if (file.size > MAX_FILE_SIZE) {
    return {
      valid: false,
      error: `文件大小超过限制。最大允许: ${MAX_FILE_SIZE / 1024 / 1024}MB`,
    };
  }

  return { valid: true };
}

/**
 * 判断文件类型
 */
export function getFileType(mimeType: string): 'image' | 'document' | 'other' {
  if (ALLOWED_FILE_TYPES.image.includes(mimeType)) return 'image';
  if (ALLOWED_FILE_TYPES.document.includes(mimeType)) return 'document';
  return 'other';
}

/**
 * 直接上传文件 (适用于小文件)
 */
export async function uploadFileDirect(
  file: File,
  userId: string,
  conversationId?: string,
  onProgress?: (progress: number) => void,
): Promise<FileInfo> {
  const formData = new FormData();
  formData.append('file', file);
  if (conversationId) {
    formData.append('conversationId', conversationId);
  }

  // 使用 XMLHttpRequest 来获取上传进度
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.upload.addEventListener('progress', (event) => {
      if (event.lengthComputable && onProgress) {
        const progress = Math.round((event.loaded / event.total) * 100);
        onProgress(progress);
      }
    });

    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        const response = JSON.parse(xhr.responseText);
        resolve(response);
      } else {
        reject(new Error(`上传失败: ${xhr.statusText}`));
      }
    });

    xhr.addEventListener('error', () => {
      reject(new Error('网络错误，上传失败'));
    });

    xhr.open('POST', '/api/v1/files/upload');
    xhr.setRequestHeader('x-user-id', userId);
    xhr.send(formData);
  });
}

/**
 * 获取预签名上传 URL (适用于大文件)
 */
export async function getPresignedUploadUrl(
  fileName: string,
  mimeType: string,
  userId: string,
  conversationId?: string,
): Promise<PresignedUrlResponse> {
  const response = await fetch('/api/v1/files/presigned-url', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-user-id': userId,
    },
    body: JSON.stringify({
      fileName,
      mimeType,
      conversationId,
    }),
  });

  if (!response.ok) {
    throw new Error('获取上传地址失败');
  }

  return response.json();
}

/**
 * 使用预签名 URL 上传文件
 */
export async function uploadFileWithPresignedUrl(
  file: File,
  uploadUrl: string,
  onProgress?: (progress: number) => void,
): Promise<void> {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.upload.addEventListener('progress', (event) => {
      if (event.lengthComputable && onProgress) {
        const progress = Math.round((event.loaded / event.total) * 100);
        onProgress(progress);
      }
    });

    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve();
      } else {
        reject(new Error(`上传失败: ${xhr.statusText}`));
      }
    });

    xhr.addEventListener('error', () => {
      reject(new Error('网络错误，上传失败'));
    });

    xhr.open('PUT', uploadUrl);
    xhr.setRequestHeader('Content-Type', file.type);
    xhr.send(file);
  });
}

/**
 * 确认上传完成
 */
export async function confirmUpload(
  fileId: string,
  fileSize: number,
  userId: string,
): Promise<FileInfo> {
  const response = await fetch(`/api/v1/files/${fileId}/confirm`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-user-id': userId,
    },
    body: JSON.stringify({ size: fileSize }),
  });

  if (!response.ok) {
    throw new Error('确认上传失败');
  }

  return response.json();
}

/**
 * 上传文件（自动选择直接上传或预签名上传）
 */
export async function uploadFile(
  file: File,
  userId: string,
  conversationId?: string,
  onProgress?: (progress: number) => void,
): Promise<FileInfo> {
  // 小文件直接上传
  if (file.size <= MAX_DIRECT_UPLOAD_SIZE) {
    return uploadFileDirect(file, userId, conversationId, onProgress);
  }

  // 大文件使用预签名 URL
  const presignedData = await getPresignedUploadUrl(
    file.name,
    file.type,
    userId,
    conversationId,
  );

  await uploadFileWithPresignedUrl(file, presignedData.uploadUrl, onProgress);

  return confirmUpload(presignedData.fileId, file.size, userId);
}

/**
 * 获取文件下载 URL
 */
export async function getFileDownloadUrl(
  fileId: string,
  userId: string,
): Promise<string> {
  const response = await fetch(`/api/v1/files/${fileId}/download-url`, {
    headers: {
      'x-user-id': userId,
    },
  });

  if (!response.ok) {
    throw new Error('获取下载地址失败');
  }

  const data = await response.json();
  return data.url;
}

/**
 * 获取用户的文件列表
 */
export async function getUserFiles(
  userId: string,
  conversationId?: string,
): Promise<FileInfo[]> {
  const params = new URLSearchParams();
  if (conversationId) {
    params.append('conversationId', conversationId);
  }

  const response = await fetch(`/api/v1/files?${params}`, {
    headers: {
      'x-user-id': userId,
    },
  });

  if (!response.ok) {
    throw new Error('获取文件列表失败');
  }

  return response.json();
}

/**
 * 删除文件
 */
export async function deleteFile(fileId: string, userId: string): Promise<void> {
  const response = await fetch(`/api/v1/files/${fileId}`, {
    method: 'DELETE',
    headers: {
      'x-user-id': userId,
    },
  });

  if (!response.ok) {
    throw new Error('删除文件失败');
  }
}
