// ============================================================
// storage-ipc.ts — 本地存储 IPC 处理器（主进程）
//
// 职责：
//   - 文件写入/读取/删除（Buffer 基础操作）
//   - 递归创建目录
//   - shell.showItemInFolder（右键"在文件夹中查看"）
//   - 获取应用数据目录路径
//   - 所有操作在 heixiu-data/ 沙箱内进行
//
// 安全：
//   - 路径校验：拒绝相对路径中的 ../ 穿越
//   - 所有写入操作 base 于 getDataDir()
// ============================================================

import { ipcMain, shell, app } from 'electron';
import fs from 'node:fs';
import path from 'node:path';
import { BIDIRECTIONAL } from '../../../shared/constants/ipc-channels';
import { logger } from '../logger';

// ---------- 内部工具 ----------

let dataDirResolver: (() => string) | null = null;

/** 注入自定义数据目录解析器（在 registerStorageIpcHandlers() 之前调用） */
export function setDataDirResolver(resolver: () => string): void {
  dataDirResolver = resolver;
}

/** 获取 heixiu-data 根目录 */
function getDataDir(): string {
  return dataDirResolver ? dataDirResolver() : path.join(app.getPath('userData'), 'heixiu-data');
}

/**
 * 将相对路径解析为绝对路径，并校验是否在 dataDir 内。
 * 防止路径穿越攻击。
 */
function resolveSafe(dataDir: string, relativePath: string): string {
  const resolved = path.resolve(dataDir, relativePath);
  if (!resolved.startsWith(dataDir + path.sep) && resolved !== dataDir) {
    throw new Error(`路径越界：${relativePath}`);
  }
  return resolved;
}

/** 确保目录存在（递归创建） */
function ensureDir(dirPath: string): void {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
}

// ---------- 注册 IPC 处理器 ----------

export function registerStorageIpcHandlers(): void {
  const dataDir = getDataDir();
  ensureDir(dataDir);
  logger.info('app', `本地存储目录：${dataDir}`);

  // ---- 获取数据目录 ----
  ipcMain.handle(BIDIRECTIONAL.GET_DATA_DIR, () => {
    return { success: true, data: dataDir };
  });

  // ---- 文件写入 ----
  ipcMain.handle(
    BIDIRECTIONAL.FILE_WRITE,
    async (
      _event,
      params: { relativePath: string; data: string; encoding?: 'base64' | 'utf8' },
    ) => {
      try {
        const filePath = resolveSafe(dataDir, params.relativePath);
        ensureDir(path.dirname(filePath));

        const buffer = Buffer.from(params.data, params.encoding || 'base64');
        fs.writeFileSync(filePath, buffer);
        console.log(`[storage IPC] 文件写入成功：${filePath}（${buffer.length} bytes）`);
        return { success: true, data: filePath };
      } catch (err) {
        const msg = (err as Error).message;
        console.error(`[storage IPC] 文件写入失败：${params.relativePath} — ${msg}`);
        logger.warn('storage', `文件写入失败：${params.relativePath}`, err instanceof Error ? err : undefined);
        return { success: false, error: msg };
      }
    },
  );

  // ---- 文件读取（返回 Base64） ----
  ipcMain.handle(BIDIRECTIONAL.FILE_READ, async (_event, params: { relativePath: string }) => {
    try {
      const filePath = resolveSafe(dataDir, params.relativePath);
      if (!fs.existsSync(filePath)) {
        return { success: false, error: '文件不存在' };
      }
      const buffer = fs.readFileSync(filePath);
      return { success: true, data: buffer.toString('base64') };
    } catch (err) {
      logger.warn('storage', `文件读取失败：${params.relativePath}`, err instanceof Error ? err : undefined);
      return { success: false, error: (err as Error).message };
    }
  });

  // ---- 文件删除 ----
  ipcMain.handle(BIDIRECTIONAL.FILE_DELETE, async (_event, params: { relativePath: string }) => {
    try {
      const filePath = resolveSafe(dataDir, params.relativePath);
      if (fs.existsSync(filePath)) {
        fs.unlinkSync(filePath);
      }
      return { success: true };
    } catch (err) {
      logger.warn('storage', `文件删除失败：${params.relativePath}`, err instanceof Error ? err : undefined);
      return { success: false, error: (err as Error).message };
    }
  });

  // ---- 创建目录 ----
  ipcMain.handle(BIDIRECTIONAL.MAKE_DIR, async (_event, params: { relativePath: string }) => {
    try {
      const dirPath = resolveSafe(dataDir, params.relativePath);
      ensureDir(dirPath);
      return { success: true, data: dirPath };
    } catch (err) {
      logger.warn('storage', `目录创建失败：${params.relativePath}`, err instanceof Error ? err : undefined);
      return { success: false, error: (err as Error).message };
    }
  });

  // ---- 在文件管理器中显示 ----
  ipcMain.handle(BIDIRECTIONAL.SHOW_ITEM_IN_FOLDER, async (_event, params: { filePath: string }) => {
    try {
      shell.showItemInFolder(params.filePath);
      return { success: true };
    } catch (err) {
      logger.warn('storage', `showItemInFolder 失败：${params.filePath}`, err instanceof Error ? err : undefined);
      return { success: false, error: (err as Error).message };
    }
  });

  // ---- 文件大小 ----
  ipcMain.handle(BIDIRECTIONAL.FILE_SIZE, async (_event, params: { relativePath: string }) => {
    try {
      const filePath = resolveSafe(dataDir, params.relativePath);
      if (!fs.existsSync(filePath)) {
        return { success: false, error: '文件不存在' };
      }
      const stat = fs.statSync(filePath);
      return { success: true, data: stat.size };
    } catch (err) {
      logger.warn('storage', '获取文件大小失败', err instanceof Error ? err : undefined);
      return { success: false, error: (err as Error).message };
    }
  });

  // ---- 文件/目录是否存在 ----
  ipcMain.handle(BIDIRECTIONAL.FILE_EXISTS, async (_event, params: { relativePath: string }) => {
    try {
      const filePath = resolveSafe(dataDir, params.relativePath);
      return { success: true, data: fs.existsSync(filePath) };
    } catch {
      return { success: true, data: false };
    }
  });

  logger.info('app', '存储 IPC 处理器已注册');
}
