/**
 * image-storage.js — 图片文件系统持久化存储
 *
 * 存储路径: data/images/{userUuid}/{hash前2字符}/{sha256hash}.{ext}
 * 按内容 hash 去重：同一用户同内容图片只存一份文件。
 */

import crypto from 'crypto';
import { promises as fs } from 'fs';
import path from 'path';

const DATA_DIR = process.env.DATA_DIR || path.join(process.cwd(), 'data');
const IMAGES_DIR = path.join(DATA_DIR, 'images');

/**
 * 计算 buffer 的 SHA-256 hex
 */
function computeHash(buffer) {
  return crypto.createHash('sha256').update(buffer).digest('hex');
}

/**
 * 构建图片文件的绝对路径
 */
function buildImagePath(userUuid, fileHash, fileExt) {
  const prefix = fileHash.substring(0, 2);
  return path.join(IMAGES_DIR, userUuid, prefix, `${fileHash}.${fileExt}`);
}

/**
 * 保存图片到文件系统（按内容 hash 去重）
 * @param {string} userUuid
 * @param {Buffer} buffer - 图片原始二进制
 * @param {string} ext - 扩展名（不含点，如 'png'）
 * @returns {Promise<{fileHash: string, alreadyExisted: boolean}>}
 */
async function saveImage(userUuid, buffer, ext) {
  const fileHash = computeHash(buffer);
  const filePath = buildImagePath(userUuid, fileHash, ext);

  try {
    await fs.access(filePath);
    return { fileHash, alreadyExisted: true };
  } catch {
    // 文件不存在，写入
  }

  await fs.mkdir(path.dirname(filePath), { recursive: true });
  await fs.writeFile(filePath, buffer);
  return { fileHash, alreadyExisted: false };
}

/**
 * 获取图片文件的绝对路径
 */
function getImagePath(userUuid, fileHash, fileExt) {
  return buildImagePath(userUuid, fileHash, fileExt);
}

/**
 * 删除图片文件（忽略不存在的情况）
 */
async function deleteImageFile(userUuid, fileHash, fileExt) {
  const filePath = buildImagePath(userUuid, fileHash, fileExt);
  try {
    await fs.unlink(filePath);
  } catch (err) {
    if (err.code !== 'ENOENT') throw err;
  }
}

/**
 * 删除用户所有图片文件目录（用户删除时调用）
 */
async function deleteUserImageDir(userUuid) {
  const userImagesDir = path.join(IMAGES_DIR, userUuid);
  try {
    await fs.rm(userImagesDir, { recursive: true, force: true });
  } catch (err) {
    if (err.code !== 'ENOENT') throw err;
  }
}

export {
  IMAGES_DIR,
  computeHash,
  saveImage,
  getImagePath,
  deleteImageFile,
  deleteUserImageDir,
};
