// Profile 存储 — 基于文件系统，每个 profile 一个目录
// 结构：data/profiles/{profileId}/meta.json + SOUL.md + config.yaml

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

const DATA_DIR = path.join(__dirname, '..', '..', 'data');
const PROFILES_DIR = path.join(DATA_DIR, 'profiles');
const QRCODES_DIR = path.join(DATA_DIR, 'qrcodes');

// profileId 格式：hermes_ + 24 位 hex（共 31 字符）
const PROFILE_ID_RE = /^hermes_[a-f0-9]{24}$/;

// P0 修复：校验 profileId 格式，防止路径穿越
function isValidProfileId(profileId) {
  return typeof profileId === 'string' && PROFILE_ID_RE.test(profileId);
}

// 确保目录存在
function ensureDirs() {
  for (const dir of [DATA_DIR, PROFILES_DIR, QRCODES_DIR]) {
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
  }
}

// 生成 profileId（hermes_ 前缀 + 随机 hex）
function generateProfileId() {
  return 'hermes_' + crypto.randomBytes(12).toString('hex');
}

// 创建 profile（P1 修复：原子写入 — 先写临时目录，全部成功后 rename）
function createProfile({ profileId, profileName, roleId, sourceBaseUrl, modelKey, provider, multimediaModelKey, multimediaProvider, enableSchedule, soulMd, configYaml, qrCodeUrl }) {
  if (!isValidProfileId(profileId)) {
    throw new Error('无效的 profileId');
  }
  ensureDirs();

  const meta = {
    profileId,
    profileName,
    roleId,
    sourceBaseUrl,
    modelKey,
    provider,
    multimediaModelKey,
    multimediaProvider,
    enableSchedule,
    qrCodeUrl,
    createdAt: new Date().toISOString(),
    boundWechat: null,
    boundAt: null,
  };

  // 写入临时目录，全部成功后原子 rename 到正式路径
  const tmpDir = path.join(PROFILES_DIR, `.tmp_${profileId}_${Date.now()}`);
  fs.mkdirSync(tmpDir, { recursive: true });

  try {
    fs.writeFileSync(path.join(tmpDir, 'meta.json'), JSON.stringify(meta, null, 2));
    fs.writeFileSync(path.join(tmpDir, 'SOUL.md'), soulMd);
    fs.writeFileSync(path.join(tmpDir, 'config.yaml'), configYaml);
    // 原子操作：rename 在同一文件系统上是原子的
    fs.renameSync(tmpDir, path.join(PROFILES_DIR, profileId));
  } catch (err) {
    // 失败时清理临时目录
    try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch {}
    throw err;
  }

  return meta;
}

// 获取 profile 元数据
function getProfileMeta(profileId) {
  if (!isValidProfileId(profileId)) return null;
  const metaPath = path.join(PROFILES_DIR, profileId, 'meta.json');
  if (!fs.existsSync(metaPath)) return null;
  return JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
}

// 获取 profile 文件内容
function getProfileFile(profileId, filename) {
  if (!isValidProfileId(profileId)) return null;
  // filename 仅允许已知文件名
  const ALLOWED_FILES = ['SOUL.md', 'config.yaml'];
  if (!ALLOWED_FILES.includes(filename)) return null;
  const filePath = path.join(PROFILES_DIR, profileId, filename);
  if (!fs.existsSync(filePath)) return null;
  return fs.readFileSync(filePath, 'utf-8');
}

// 列出所有 profile（P2 修复：跳过损坏的 meta.json）
function listProfiles() {
  ensureDirs();
  const entries = fs.readdirSync(PROFILES_DIR, { withFileTypes: true });
  const profiles = [];
  for (const entry of entries) {
    if (entry.isDirectory() && !entry.name.startsWith('.tmp_')) {
      try {
        const meta = getProfileMeta(entry.name);
        if (meta) profiles.push(meta);
      } catch (err) {
        console.warn(`[Hermes] 跳过损坏的 profile: ${entry.name}`, err.message);
      }
    }
  }
  // 按创建时间倒序
  profiles.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
  return profiles;
}

// 绑定微信（P1 修复：原子检查 — 写入前再次校验未绑定）
function bindWechat(profileId, wechatId) {
  if (!isValidProfileId(profileId)) return null;
  const meta = getProfileMeta(profileId);
  if (!meta) return null;

  // 原子检查：若已绑定则拒绝（防止 TOCTOU 竞态）
  if (meta.boundWechat) return { alreadyBound: true };

  meta.boundWechat = wechatId;
  meta.boundAt = new Date().toISOString();

  // 原子写入：先写临时文件再 rename
  const metaPath = path.join(PROFILES_DIR, profileId, 'meta.json');
  const tmpPath = path.join(PROFILES_DIR, profileId, `.meta.json.tmp_${Date.now()}`);
  fs.writeFileSync(tmpPath, JSON.stringify(meta, null, 2));
  fs.renameSync(tmpPath, metaPath);

  return meta;
}

// 删除 profile（P0 修复：校验 profileId 防止路径穿越）
function deleteProfile(profileId) {
  if (!isValidProfileId(profileId)) return false;
  const dir = path.join(PROFILES_DIR, profileId);
  if (!fs.existsSync(dir)) return false;
  fs.rmSync(dir, { recursive: true });
  // 同时清理二维码
  const qrPath = path.join(QRCODES_DIR, `${profileId}.png`);
  if (fs.existsSync(qrPath)) {
    try { fs.unlinkSync(qrPath); } catch {}
  }
  return true;
}

// 保存二维码图片
function saveQrCode(profileId, pngBuffer) {
  if (!isValidProfileId(profileId)) {
    throw new Error('无效的 profileId');
  }
  ensureDirs();
  const filename = `${profileId}.png`;
  fs.writeFileSync(path.join(QRCODES_DIR, filename), pngBuffer);
  return filename;
}

// 获取二维码图片路径
function getQrCodePath(profileId) {
  if (!isValidProfileId(profileId)) return null;
  const filePath = path.join(QRCODES_DIR, `${profileId}.png`);
  if (!fs.existsSync(filePath)) return null;
  return filePath;
}

// 根据 roleId 查找已有 profile（P1 修复：幂等去重）
function findByRoleId(roleId) {
  if (!roleId) return null;
  const profiles = listProfiles();
  return profiles.find((p) => p.roleId === roleId) || null;
}

module.exports = {
  ensureDirs,
  generateProfileId,
  createProfile,
  getProfileMeta,
  getProfileFile,
  listProfiles,
  bindWechat,
  deleteProfile,
  saveQrCode,
  getQrCodePath,
  findByRoleId,
};
