/**
 * 基于 expo-file-system 的 MobileBeanBackend 实现。
 *
 * 替代 MemoryBackend，让 main.bean 真正持久化到磁盘：
 * - read()：读取 documentDirectory/main.bean，不存在返回空串
 * - writeAtomic()：写 tmp → 删旧文件 → 重命名 tmp（最佳努力的原子写入）
 * - recoverIfNeeded()：检测并清理上次崩溃 of tmp 残留
 */

import * as FileSystem from 'expo-file-system/legacy';
import type { MobileBeanBackend } from '../../domain/platform/mobileStore';
import { logger } from '../../utils/logger';

const FILE_PATH = (FileSystem.documentDirectory ?? '') + 'main.bean';
const TMP_PATH = (FileSystem.documentDirectory ?? '') + 'main.bean.tmp';

/**
 * 文件系统后端：持久化 main.bean 到磁盘。
 *
 * 原子写入策略：先写 .tmp，再删除旧文件，最后 rename。
 * expo-file-system 的 moveAsync 不保证跨文件系统原子性，
 * 但 tmp+rename 在同一 documentDirectory 下是可靠的。
 */
export class FileSystemBackend implements MobileBeanBackend {
  async read(): Promise<string> {
    try {
      const info = await FileSystem.getInfoAsync(FILE_PATH);
      if (!info.exists) return '';
      return await FileSystem.readAsStringAsync(FILE_PATH);
    } catch (e) {
      logger.error('FileSystemBackend', `read failed: ${e}`);
      return '';
    }
  }

  async writeAtomic(content: string): Promise<void> {
    // 1. 写入临时文件
    await FileSystem.writeAsStringAsync(TMP_PATH, content);
    // 2. 重命名 tmp → 正式文件（同目录 moveAsync 覆盖目标，保证中途崩溃不损坏原文件）
    await FileSystem.moveAsync({ from: TMP_PATH, to: FILE_PATH });
  }

  async recoverIfNeeded(): Promise<boolean> {
    try {
      const tmpInfo = await FileSystem.getInfoAsync(TMP_PATH);
      if (tmpInfo.exists) {
        const fileInfo = await FileSystem.getInfoAsync(FILE_PATH);
        if (fileInfo.exists) {
          // 正式文件存在：tmp 是崩溃残留，丢弃
          await FileSystem.deleteAsync(TMP_PATH, { idempotent: true });
        } else {
          // 正式文件不存在：rename 中崩溃，用 tmp 恢复
          await FileSystem.moveAsync({ from: TMP_PATH, to: FILE_PATH });
        }
        logger.warn('FileSystemBackend', 'Recovered from crashed write (tmp residue cleaned)');
        return true;
      }
      return false;
    } catch {
      return false;
    }
  }
}
