/**
 * 本地备份与恢复（plan.md「0.5 本地备份与恢复」）。
 * 备份的核心是 .bean 文件 + 设置 + 元数据（分类/规则/预算等）。
 *
 * 本模块定义备份/恢复的纯逻辑（内容打包/解包），
 * 文件系统操作通过注入的 backend 抽象。
 */

import { hash } from '../../domain/core/ledger';
import type { LedgerFile } from '../../domain/core/types';
import { logger } from '../../utils/logger';

/** 备份内容（序列化为 JSON 后打包）。 */
export interface BackupBundle {
  version: 1 | 2;
  createdAt: string;
  files: { path: string; content: string }[];
  /** main.bean 的内容（v1 格式字段名为 mobileBean，此处做兼容）。 */
  mainBean: string;
  /** v2 新增：用户设置（语言/主题等，不含敏感字段）。 */
  settings?: Record<string, unknown>;
  /** v2 新增：元数据（分类/标签/预算/信用卡/规则）。 */
  metadata?: Record<string, unknown>;
}

export interface BackupBackend {
  /** 打包为 zip 并保存，返回路径。 */
  writeZip(bundle: BackupBundle): Promise<string>;
  /** 读取 zip 并解析为 bundle。 */
  readZip(uri: string): Promise<BackupBundle>;
  /** 选择文档（用户选 zip 文件）。 */
  pickDocument(): Promise<string | null>;
}

/** 创建备份 bundle（含设置和元数据）。 */
export function createBackupBundle(
  files: LedgerFile[],
  mainBean: string,
  settings?: Record<string, unknown>,
  metadata?: Record<string, unknown>,
): BackupBundle {
  const bundle: BackupBundle = {
    version: 2,
    createdAt: new Date().toISOString(),
    files: files.filter(f => f.path !== 'main.bean'),
    mainBean,
    settings,
    metadata,
  };
  logger.info('backup', `创建本地备份包成功 (文件数: ${bundle.files.length + 1}, 含设置/元数据)`);
  return bundle;
}

/** 序列化为 JSON（便于打包/传输）。 */
export function serializeBundle(bundle: BackupBundle): string {
  return JSON.stringify(bundle, null, 2);
}

/** 反序列化 + 校验（兼容 v1 和 v2，以及旧版 mobileBean 字段名）。 */
export function deserializeBundle(json: string): BackupBundle {
  try {
    const data = JSON.parse(json) as Record<string, unknown>;
    if (data.version !== 1 && data.version !== 2) throw new Error(`不支持的备份版本: ${data.version}`);
    if (!Array.isArray(data.files)) throw new Error('备份文件格式错误：files 非数组');
    // 兼容旧版 mobileBean 字段名
    const mainBean = (typeof data.mainBean === 'string' ? data.mainBean : undefined)
      ?? (typeof data.mobileBean === 'string' ? data.mobileBean as string : undefined);
    if (typeof mainBean !== 'string') throw new Error('备份文件格式错误：mainBean 非字符串');
    const result = { ...data, mainBean } as BackupBundle;
    logger.info('backup', `反序列化备份包成功 (版本: v${result.version}, 创建时间: ${result.createdAt})`);
    return result;
  } catch (e) {
    logger.error('backup', `解析备份包 JSON 失败: ${e instanceof Error ? e.message : String(e)}`);
    throw e;
  }
}

/** 计算备份的校验和（用于完整性校验）。 */
export function bundleChecksum(bundle: BackupBundle): string {
  return hash(serializeBundle(bundle));
}

/** 从 bundle 恢复文件列表（含 main.bean）。 */
export function restoreFiles(bundle: BackupBundle): LedgerFile[] {
  return [
    ...bundle.files,
    { path: 'main.bean', content: bundle.mainBean },
  ];
}
