import { Injectable } from '@angular/core';
import { NovaStorage, NovaFile } from 'fmode-ng/core';
import { FmodeParse, FmodeObject } from 'fmode-ng/parse';

const Parse = FmodeParse.with('nova');

@Injectable({
  providedIn: 'root'
})
export class ProjectFileService {

  /**
   * 上传项目文件并保存到ProjectFile表
   * @param file 要上传的文件
   * @param projectId 项目ID
   * @param fileType 文件类型
   * @param spaceId 空间ID（可选）
   * @param stage 项目阶段（可选）
   * @param additionalMetadata 额外元数据（可选）
   * @param onProgress 上传进度回调
   * @returns 上传后的NovaFile对象
   */
  async uploadProjectFile(
    file: File,
    projectId: string,
    fileType: string,
    spaceId?: string,
    stage?: string,
    additionalMetadata?: any,
    onProgress?: (progress: number) => void
  ): Promise<NovaFile> {
    try {
      // 获取公司ID
      const cid = localStorage.getItem('company');
      if (!cid) {
        throw new Error('公司ID未找到');
      }

      // 初始化存储
      const storage = await NovaStorage.withCid(cid);

      // 构建prefixKey
      let prefixKey = `project/${projectId}`;
      if (spaceId) {
        prefixKey += `/space/${spaceId}`;
      }
      if (stage) {
        prefixKey += `/stage/${stage}`;
      }

      // 上传文件
      const uploadedFile: NovaFile = await storage.upload(file, {
        prefixKey,
        onProgress: (progress) => {
          if (onProgress) {
            onProgress(progress.total.percent);
          }
        }
      });

      // 保存到Attachment表
      await this.saveToAttachmentTable(uploadedFile, projectId, fileType, spaceId, stage, additionalMetadata);

      return uploadedFile;

    } catch (error) {
      console.error('项目文件上传失败:', error);
      throw error;
    }
  }

  /**
   * 保存文件信息到Attachment表
   */
  private async saveToAttachmentTable(
    file: NovaFile,
    projectId: string,
    fileType: string,
    spaceId?: string,
    stage?: string,
    additionalMetadata?: any
  ): Promise<FmodeObject> {
    const Attachment = Parse.Object.extend('Attachment');
    const attachment = new Attachment();

    // 设置基本字段
    attachment.set('size', file.size);
    attachment.set('url', file.url);
    attachment.set('name', file.name);
    attachment.set('mime', file.type);
    attachment.set('md5', file.md5);
    attachment.set('metadata', {
      ...file.metadata,
      projectId,
      fileType,
      spaceId,
      stage,
      ...additionalMetadata
    });

    // 设置关联关系
    const cid = localStorage.getItem('company');
    if (cid) {
      const companyQuery = new Parse.Query('Company');
      companyQuery.equalTo('corpId', cid);
      const company = await companyQuery.first();
      if (company) {
        attachment.set('company', company);
      }
    }

    // 设置当前用户
    const currentUser = Parse.User.current();
    if (currentUser) {
      attachment.set('user', currentUser);
    }

    const savedAttachment = await attachment.save();
    return savedAttachment;
  }

  /**
   * 保存到ProjectFile表
   */
  async saveToProjectFile(
    attachment: FmodeObject,
    projectId: string,
    fileType: string,
    spaceId?: string,
    stage?: string
  ): Promise<FmodeObject> {
    const ProjectFile = Parse.Object.extend('ProjectFile');
    const projectFile = new ProjectFile();

    // 获取项目
    const projectQuery = new Parse.Query('Project');
    const project = await projectQuery.get(projectId);

    // 设置字段
    projectFile.set('project', project);
    projectFile.set('attach', attachment);
    projectFile.set('fileType', fileType);
    projectFile.set('fileUrl', attachment.get('url'));
    projectFile.set('fileName', attachment.get('name'));
    projectFile.set('fileSize', attachment.get('size'));

    if (stage) {
      projectFile.set('stage', stage);
    }

    // 新增：从附件元数据中读取 deliverableId 并写入 ProjectFile.data
    const deliverableId = attachment.get('metadata')?.deliverableId;
    const data = {
      spaceId,
      uploadedAt: new Date(),
      fileType,
      deliverableId,
      metadata: attachment.get('metadata')
    };
    projectFile.set('data', data);

    // 设置上传者
    const currentUser = Parse.User.current();
    if (currentUser) {
      projectFile.set('uploadedBy', currentUser);
    }

    const savedProjectFile = await projectFile.save();
    return savedProjectFile;
  }

  /**
   * 删除项目文件
   */
  async deleteProjectFile(projectFileId: string): Promise<void> {
    try {
      // 删除ProjectFile记录
      const ProjectFile = Parse.Object.extend('ProjectFile');
      const query = new Parse.Query(ProjectFile);
      const projectFile = await query.get(projectFileId);

      // 删除Attachment记录
      const attachment = projectFile.get('attach');
      if (attachment) {
        await attachment.destroy();
      }

      // 删除ProjectFile记录
      await projectFile.destroy();

    } catch (error) {
      console.error('删除项目文件失败:', error);
      throw error;
    }
  }

  /**
   * 获取项目文件列表
   */
  async getProjectFiles(
    projectId: string,
    filters?: {
      fileType?: string;
      spaceId?: string;
      stage?: string;
    }
  ): Promise<FmodeObject[]> {
    try {
      const ProjectFile = Parse.Object.extend('ProjectFile');
      const query = new Parse.Query(ProjectFile);

      // 关联项目查询
      const Project = Parse.Object.extend('Project');
      const projectQuery = new Parse.Query(Project);
      projectQuery.equalTo('objectId', projectId);

      query.matchesQuery('project', projectQuery);
      query.include('attach', 'uploadedBy');
      query.descending('createdAt');

      // 应用过滤器
      if (filters?.fileType) {
        query.equalTo('fileType', filters.fileType);
      }
      if (filters?.stage) {
        query.equalTo('stage', filters.stage);
      }

      const results = await query.find();

      // 如果有空间ID过滤，从data中筛选
      if (filters?.spaceId) {
        return results.filter(result => {
          const data = result.get('data');
          return data?.spaceId === filters.spaceId;
        });
      }

      return results;

    } catch (error) {
      console.error('获取项目文件列表失败:', error);
      throw error;
    }
  }

  /**
   * 批量上传文件
   */
  async uploadMultipleFiles(
    files: File[],
    projectId: string,
    fileType: string,
    spaceId?: string,
    stage?: string,
    onProgress?: (fileIndex: number, progress: number) => void
  ): Promise<NovaFile[]> {
    const results: NovaFile[] = [];

    for (let i = 0; i < files.length; i++) {
      const file = files[i];

      try {
        const uploadedFile = await this.uploadProjectFile(
          file,
          projectId,
          fileType,
          spaceId,
          stage,
          undefined,
          (progress) => {
            if (onProgress) {
              onProgress(i, progress);
            }
          }
        );
        results.push(uploadedFile);
      } catch (error) {
        console.error(`文件 ${file.name} 上传失败:`, error);
        // 继续上传其他文件
      }
    }

    return results;
  }

  /**
   * 验证文件
   */
  validateFile(file: File, maxSize: number = 50 * 1024 * 1024, allowedTypes?: string[]): boolean {
    // 检查文件大小
    if (file.size > maxSize) {
      return false;
    }

    // 检查文件类型
    if (allowedTypes && !allowedTypes.includes(file.type)) {
      return false;
    }

    return true;
  }

  /**
   * 获取文件类型标签
   */
  getFileTypeLabel(fileType: string): string {
    const typeMap: Record<string, string> = {
      'image/jpeg': '图片',
      'image/png': '图片',
      'image/gif': '图片',
      'image/webp': '图片',
      'video/mp4': '视频',
      'video/mov': '视频',
      'video/avi': '视频',
      'application/pdf': 'PDF',
      'application/msword': 'Word',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word',
      'application/vnd.ms-excel': 'Excel',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'Excel',
      'application/vnd.ms-powerpoint': 'PPT',
      'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'PPT'
    };

    return typeMap[fileType] || '其他';
  }

  /**
   * 格式化文件大小
   */
  formatFileSize(bytes: number): string {
    if (bytes === 0) return '0 B';

    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }

  /**
   * 上传文件并创建 Attachment 与 ProjectFile 记录，返回 ProjectFile
   */
  async uploadProjectFileWithRecord(
    file: File,
    projectId: string,
    fileType: string,
    spaceId?: string,
    stage?: string,
    additionalMetadata?: any,
    onProgress?: (progress: number) => void
  ): Promise<FmodeObject> {
    try {
      const cid = localStorage.getItem('company');
      if (!cid) {
        throw new Error('公司ID未找到');
      }

      const storage = await NovaStorage.withCid(cid);

      let prefixKey = `project/${projectId}`;
      if (spaceId) {
        prefixKey += `/space/${spaceId}`;
      }
      if (stage) {
        prefixKey += `/stage/${stage}`;
      }

      const uploadedFile = await storage.upload(file, {
        prefixKey,
        onProgress: (progress) => {
          if (onProgress) {
            onProgress(progress.total.percent);
          }
        }
      });

      const attachment = await this.saveToAttachmentTable(
        uploadedFile,
        projectId,
        fileType,
        spaceId,
        stage,
        additionalMetadata
      );

      const projectFile = await this.saveToProjectFile(
        attachment,
        projectId,
        fileType,
        spaceId,
        stage
      );

      return projectFile;
    } catch (error) {
      console.error('上传并创建ProjectFile失败:', error);
      throw error;
    }
  }
}