import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
import dayjs from 'dayjs';
import path from 'path';
import fs from 'fs';
import { cache, logger, utils } from '@certd/basic';
import { NotFoundException, ParamException, PermissionException } from '../../../basic/index.js';

export type UploadFileItem = {
  filename: string;
  tmpFilePath: string;
};
const uploadRootDir = './data/upload';
export const uploadTmpFileCacheKey = 'tmpfile_key_';
/**
 */
@Provide()
@Scope(ScopeEnum.Singleton)
export class FileService {
  async saveFile(userId: number, tmpCacheKey: any, permission: 'public' | 'private') {
    if (tmpCacheKey.startsWith(`/${permission}`)) {
      //已经保存过，不需要再次保存
      return tmpCacheKey;
    }
    let fileName = '';
    let tmpFilePath = tmpCacheKey;
    if (uploadTmpFileCacheKey && tmpCacheKey.startsWith(uploadTmpFileCacheKey)) {
      const tmpFile: UploadFileItem = cache.get(tmpCacheKey);
      if (!tmpFile) {
        throw new ParamException('文件已过期，请重新上传');
      }
      tmpFilePath = tmpFile.tmpFilePath;
      fileName = tmpFile.filename || path.basename(tmpFilePath);
    }
    if (!tmpFilePath || !fs.existsSync(tmpFilePath)) {
      throw new Error('文件不存在,请重新上传');
    }
    const date = dayjs().format('YYYY_MM_DD');
    const random = Math.random().toString(36).substring(7);
    const userIdMd5 = Buffer.from(Buffer.from(userId + '').toString('base64')).toString('hex');
    const key = `/${permission}/${userIdMd5}/${date}/${random}_${fileName}`;
    let savePath = path.join(uploadRootDir, key);
    savePath = path.resolve(savePath);
    const parentDir = path.dirname(savePath);
    if (!fs.existsSync(parentDir)) {
      fs.mkdirSync(parentDir, { recursive: true });
    }
    // eslint-disable-next-line node/no-unsupported-features/node-builtins
    const copyFile = utils.promises.promisify(fs.copyFile);
    await copyFile(tmpFilePath, savePath);
    try {
      fs.unlinkSync(tmpFilePath);
    } catch (e) {
      logger.error(e);
    }

    return key;
  }

  getFile(key: string, userId?: number) {
    if (!key) {
      throw new ParamException('参数错误');
    }
    if (key.indexOf('..') >= 0) {
      //安全性判断
      throw new ParamException('参数错误');
    }
    if (!key.startsWith('/')) {
      throw new ParamException('参数错误');
    }
    const keyArr = key.split('/');
    const permission = keyArr[1];
    const userIdMd5 = keyArr[2];
    if (permission !== 'public') {
      //非公开文件需要验证用户
      const userIdStr = Buffer.from(Buffer.from(userIdMd5, 'hex').toString('base64')).toString();
      const userIdInt: number = parseInt(userIdStr, 10);
      if (userId == null || userIdInt !== userId) {
        throw new PermissionException('无访问权限');
      }
    }
    const filePath = path.join(uploadRootDir, key);
    if (!fs.existsSync(filePath)) {
      throw new NotFoundException('文件不存在');
    }
    return filePath;
  }
}
