import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:archive/archive.dart';
import 'package:archive/archive_io.dart';
import 'package:file_picker/file_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:share_plus/share_plus.dart';
import '../database_helper.dart';
import '../user_prefs.dart';

/// 数据备份服务 - 支持导出和导入数据（包含图片）
class BackupService {
  static final BackupService instance = BackupService._init();
  
  BackupService._init();
  
  /// 导出所有数据和图片为 ZIP 文件，并选择保存路径
  Future<ExportResult> exportDataWithImages() async {
    try {
      final db = await DatabaseHelper.instance.database;
      
      // 导出所有表的数据
      final movies = await db.query('movies');
      final books = await db.query('books');
      final notes = await db.query('notes');
      final movieReviews = await db.query('movie_reviews');
      final moviePosters = await db.query('movie_posters');
      final bookReviews = await db.query('book_reviews');
      final bookExcerpts = await db.query('book_excerpts');
      final tags = await db.query('tags');
      
      // 收集所有图片路径
      final imagePaths = <String>{};
      
      // 收集影视海报
      for (final movie in movies) {
        final posterPath = movie['poster_path'] as String?;
        if (posterPath != null && posterPath.isNotEmpty) {
          imagePaths.add(posterPath);
        }
      }
      
      // 收集书籍封面
      for (final book in books) {
        final coverPath = book['cover_path'] as String?;
        if (coverPath != null && coverPath.isNotEmpty) {
          imagePaths.add(coverPath);
        }
      }
      
      // 收集海报墙图片
      for (final poster in moviePosters) {
        final posterPath = poster['poster_path'] as String?;
        if (posterPath != null && posterPath.isNotEmpty) {
          imagePaths.add(posterPath);
        }
      }
      
      // 收集笔记图片
      for (final note in notes) {
        final imagesJson = note['images'] as String?;
        if (imagesJson != null && imagesJson.isNotEmpty) {
          try {
            final images = jsonDecode(imagesJson) as List<dynamic>;
            for (final imagePath in images) {
              if (imagePath is String && imagePath.isNotEmpty) {
                imagePaths.add(imagePath);
              }
            }
          } catch (e) {
            // 解析失败，跳过
          }
        }
      }
      
      // 获取用户个人信息
      final userPrefs = UserPrefs();
      final userInfo = {
        'nickname': userPrefs.nickname,
        'motto': userPrefs.motto,
        'avatarPath': userPrefs.avatarPath,
      };
      
      // 如果有头像，添加到图片路径
      final avatarPath = userPrefs.avatarPath;
      if (avatarPath != null && avatarPath.isNotEmpty) {
        imagePaths.add(avatarPath);
      }
      
      // 构建备份数据
      final backupData = {
        'version': 2,
        'exportTime': DateTime.now().toIso8601String(),
        'appName': 'MookNote',
        'hasImages': true,
        'userInfo': userInfo,
        'data': {
          'movies': movies,
          'books': books,
          'notes': notes,
          'movie_reviews': movieReviews,
          'movie_posters': moviePosters,
          'book_reviews': bookReviews,
          'book_excerpts': bookExcerpts,
          'tags': tags,
        },
      };
      
      // 创建 ZIP 文件
      final archive = Archive();
      
      // 添加 JSON 数据
      final jsonString = const JsonEncoder.withIndent('  ').convert(backupData);
      final jsonBytes = Uint8List.fromList(utf8.encode(jsonString));
      archive.addFile(ArchiveFile('data.json', jsonBytes.length, jsonBytes));
      
      // 添加图片文件，保持目录结构
      int imageCount = 0;
      final appDir = await getApplicationDocumentsDirectory();
      final imagesRoot = path.join(appDir.path, 'images');
      
      for (final imagePath in imagePaths) {
        final file = File(imagePath);
        if (await file.exists()) {
          final bytes = await file.readAsBytes();
          // 计算相对路径（如 movies/1/poster.jpg）
          String relativePath;
          if (imagePath.startsWith(imagesRoot)) {
            relativePath = imagePath.substring(imagesRoot.length + 1); // +1 去掉开头的 /
          } else {
            relativePath = path.basename(imagePath);
          }
          // 使用相对路径存储图片，保持目录结构
          archive.addFile(ArchiveFile('images/$relativePath', bytes.length, bytes));
          imageCount++;
        }
      }
      
      // 压缩 ZIP
      final zipEncoder = ZipEncoder();
      final zipBytes = zipEncoder.encode(archive);
      if (zipBytes == null) {
        return ExportResult.error('压缩备份文件失败');
      }
      
      // 保存到临时目录
      final tempDir = await getTemporaryDirectory();
      final fileName = 'mooknote_backup_${_formatDateTime(DateTime.now())}.zip';
      final tempFilePath = path.join(tempDir.path, fileName);
      final tempFile = File(tempFilePath);
      await tempFile.writeAsBytes(zipBytes);
      
      // 在移动端使用分享功能，让用户选择保存位置
      // 在桌面端可以尝试使用 saveFile
      String? finalPath;
      
      try {
        // 尝试使用系统保存对话框（桌面端支持）
        final outputPath = await FilePicker.platform.saveFile(
          dialogTitle: '保存备份文件',
          fileName: fileName,
          type: FileType.custom,
          allowedExtensions: ['zip'],
          bytes: Uint8List.fromList(zipBytes),  // 在移动端需要提供 bytes
        );
        
        if (outputPath == null) {
          // 用户取消，返回临时文件路径
          finalPath = tempFilePath;
        } else {
          finalPath = outputPath;
          // 如果保存路径不是临时文件路径，需要复制过去
          if (finalPath != tempFilePath) {
            final outputFile = File(finalPath);
            await outputFile.writeAsBytes(zipBytes);
          }
        }
      } catch (e) {
        // 如果 saveFile 失败，使用临时文件路径
        finalPath = tempFilePath;
      }
      
      return ExportResult.success(
        filePath: finalPath,
        movieCount: movies.length,
        bookCount: books.length,
        noteCount: notes.length,
        imageCount: imageCount,
      );
    } catch (e) {
      return ExportResult.error('导出失败: $e');
    }
  }
  
  /// 分享备份文件
  Future<void> shareBackup(String filePath) async {
    final file = XFile(filePath);
    await Share.shareXFiles(
      [file],
      subject: 'MookNote 数据备份',
      text: '这是我的 MookNote 数据备份文件',
    );
  }
  
  /// 导出数据用于自动备份（返回字节数据而不是保存到文件）
  Future<AutoBackupExportResult> exportDataForAutoBackup() async {
    try {
      final db = await DatabaseHelper.instance.database;
      
      // 导出所有表的数据
      final movies = await db.query('movies');
      final books = await db.query('books');
      final notes = await db.query('notes');
      final movieReviews = await db.query('movie_reviews');
      final moviePosters = await db.query('movie_posters');
      final bookReviews = await db.query('book_reviews');
      final bookExcerpts = await db.query('book_excerpts');
      final tags = await db.query('tags');
      
      // 收集所有图片路径
      final imagePaths = <String>{};
      
      // 收集影视海报
      for (final movie in movies) {
        final posterPath = movie['poster_path'] as String?;
        if (posterPath != null && posterPath.isNotEmpty) {
          imagePaths.add(posterPath);
        }
      }
      
      // 收集书籍封面
      for (final book in books) {
        final coverPath = book['cover_path'] as String?;
        if (coverPath != null && coverPath.isNotEmpty) {
          imagePaths.add(coverPath);
        }
      }
      
      // 收集海报墙图片
      for (final poster in moviePosters) {
        final posterPath = poster['poster_path'] as String?;
        if (posterPath != null && posterPath.isNotEmpty) {
          imagePaths.add(posterPath);
        }
      }
      
      // 收集笔记图片
      for (final note in notes) {
        final imagesJson = note['images'] as String?;
        if (imagesJson != null && imagesJson.isNotEmpty) {
          try {
            final images = jsonDecode(imagesJson) as List<dynamic>;
            for (final imagePath in images) {
              if (imagePath is String && imagePath.isNotEmpty) {
                imagePaths.add(imagePath);
              }
            }
          } catch (e) {
            // 解析失败，跳过
          }
        }
      }
      
      // 获取用户个人信息
      final userPrefs = UserPrefs();
      final userInfo = {
        'nickname': userPrefs.nickname,
        'motto': userPrefs.motto,
        'avatarPath': userPrefs.avatarPath,
      };
      
      // 如果有头像，添加到图片路径
      final avatarPath = userPrefs.avatarPath;
      if (avatarPath != null && avatarPath.isNotEmpty) {
        imagePaths.add(avatarPath);
      }
      
      // 构建备份数据
      final backupData = {
        'version': 2,
        'exportTime': DateTime.now().toIso8601String(),
        'appName': 'MookNote',
        'hasImages': true,
        'userInfo': userInfo,
        'data': {
          'movies': movies,
          'books': books,
          'notes': notes,
          'movie_reviews': movieReviews,
          'movie_posters': moviePosters,
          'book_reviews': bookReviews,
          'book_excerpts': bookExcerpts,
          'tags': tags,
        },
      };
      
      // 创建 ZIP 文件
      final archive = Archive();
      
      // 添加 JSON 数据
      final jsonString = const JsonEncoder.withIndent('  ').convert(backupData);
      final jsonBytes = Uint8List.fromList(utf8.encode(jsonString));
      archive.addFile(ArchiveFile('data.json', jsonBytes.length, jsonBytes));
      
      // 添加图片文件，保持目录结构
      int imageCount = 0;
      final appDir = await getApplicationDocumentsDirectory();
      final imagesRoot = path.join(appDir.path, 'images');
      
      for (final imagePath in imagePaths) {
        final file = File(imagePath);
        if (await file.exists()) {
          final bytes = await file.readAsBytes();
          // 计算相对路径（如 movies/1/poster.jpg）
          String relativePath;
          if (imagePath.startsWith(imagesRoot)) {
            relativePath = imagePath.substring(imagesRoot.length + 1);
          } else {
            relativePath = path.basename(imagePath);
          }
          // 使用相对路径存储图片，保持目录结构
          archive.addFile(ArchiveFile('images/$relativePath', bytes.length, bytes));
          imageCount++;
        }
      }
      
      // 压缩 ZIP
      final zipEncoder = ZipEncoder();
      final zipBytes = zipEncoder.encode(archive);
      if (zipBytes == null) {
        return AutoBackupExportResult.error('压缩备份文件失败');
      }
      
      return AutoBackupExportResult.success(
        zipBytes: Uint8List.fromList(zipBytes),
        movieCount: movies.length,
        bookCount: books.length,
        noteCount: notes.length,
        imageCount: imageCount,
      );
    } catch (e) {
      return AutoBackupExportResult.error('导出失败: $e');
    }
  }
  
  /// 选择并导入备份文件（支持 ZIP 格式）
  Future<ImportResult> importData() async {
    try {
      // 选择文件
      final result = await FilePicker.platform.pickFiles(
        type: FileType.custom,
        allowedExtensions: ['zip', 'json'],
        allowMultiple: false,
      );
      
      if (result == null || result.files.isEmpty) {
        return ImportResult.cancelled();
      }
      
      final filePath = result.files.first.path;
      if (filePath == null) {
        return ImportResult.error('无法读取文件路径');
      }
      
      final file = File(filePath);
      final extension = path.extension(filePath).toLowerCase();
      
      Map<String, dynamic> backupData;
      int imageCount = 0;
      // 记录图片文件名到新路径的映射
      final imagePathMap = <String, String>{};
      
      if (extension == '.zip') {
        // 处理 ZIP 文件
        final bytes = await file.readAsBytes();
        final archive = ZipDecoder().decodeBytes(bytes);
        
        // 查找 data.json
        final dataFile = archive.findFile('data.json');
        if (dataFile == null) {
          return ImportResult.error('备份文件中没有找到数据文件');
        }
        
        final jsonString = utf8.decode(dataFile.content as List<int>);
        backupData = jsonDecode(jsonString) as Map<String, dynamic>;
        
        // 解压图片到应用目录，保持目录结构
        final appDir = await getApplicationDocumentsDirectory();
        final imagesDir = Directory(path.join(appDir.path, 'images'));
        if (!await imagesDir.exists()) {
          await imagesDir.create(recursive: true);
        }
        
        for (final archiveFile in archive) {
          if (archiveFile.name.startsWith('images/')) {
            // 获取相对路径（如 movies/1/poster.jpg）
            final relativePath = archiveFile.name.substring(7); // 去掉 'images/' 前缀
            final outputFile = File(path.join(imagesDir.path, relativePath));
            
            // 确保父目录存在
            final parentDir = outputFile.parent;
            if (!await parentDir.exists()) {
              await parentDir.create(recursive: true);
            }
            
            await outputFile.writeAsBytes(archiveFile.content as List<int>);
            
            // 记录文件名到新路径的映射（用于更新数据库中的路径）
            final fileName = path.basename(archiveFile.name);
            imagePathMap[fileName] = outputFile.path;
            imageCount++;
          }
        }
      } else {
        // 处理旧版 JSON 文件
        final jsonString = await file.readAsString();
        backupData = jsonDecode(jsonString) as Map<String, dynamic>;
      }
      
      // 验证备份格式
      if (!backupData.containsKey('data')) {
        return ImportResult.error('无效的备份文件格式');
      }
      
      // 导入数据
      final data = backupData['data'] as Map<String, dynamic>;
      final db = await DatabaseHelper.instance.database;
      
      // 开始事务
      await db.transaction((txn) async {
        // 清空现有数据
        await txn.delete('movie_reviews');
        await txn.delete('movie_posters');
        await txn.delete('book_reviews');
        await txn.delete('book_excerpts');
        await txn.delete('movies');
        await txn.delete('books');
        await txn.delete('notes');
        await txn.delete('tags');
        
        // 导入影视数据（更新图片路径）
        if (data.containsKey('movies')) {
          final movies = data['movies'] as List<dynamic>;
          for (final movie in movies) {
            final movieMap = _convertToDbMap(movie);
            final updatedMap = _updateImagePath(movieMap, 'poster_path', imagePathMap);
            await txn.insert('movies', updatedMap);
          }
        }
        
        // 导入书籍数据（更新图片路径）
        if (data.containsKey('books')) {
          final books = data['books'] as List<dynamic>;
          for (final book in books) {
            final bookMap = _convertToDbMap(book);
            final updatedMap = _updateImagePath(bookMap, 'cover_path', imagePathMap);
            await txn.insert('books', updatedMap);
          }
        }
        
        // 导入笔记数据（更新图片路径）
        if (data.containsKey('notes')) {
          final notes = data['notes'] as List<dynamic>;
          for (final note in notes) {
            final noteMap = _convertToDbMap(note);
            final updatedMap = _updateNoteImagesPath(noteMap, imagePathMap);
            await txn.insert('notes', updatedMap);
          }
        }
        
        // 导入影评数据
        if (data.containsKey('movie_reviews')) {
          final reviews = data['movie_reviews'] as List<dynamic>;
          for (final review in reviews) {
            await txn.insert('movie_reviews', _convertToDbMap(review));
          }
        }
        
        // 导入海报墙数据（更新图片路径）
        if (data.containsKey('movie_posters')) {
          final posters = data['movie_posters'] as List<dynamic>;
          for (final poster in posters) {
            final posterMap = _convertToDbMap(poster);
            final updatedMap = _updateImagePath(posterMap, 'poster_path', imagePathMap);
            await txn.insert('movie_posters', updatedMap);
          }
        }
        // 导入书评数据
        if (data.containsKey('book_reviews')) {
          final reviews = data['book_reviews'] as List<dynamic>;
          for (final review in reviews) {
            await txn.insert('book_reviews', _convertToDbMap(review));
          }
        }
        // 导入书摘数据
        if (data.containsKey('book_excerpts')) {
          final excerpts = data['book_excerpts'] as List<dynamic>;
          for (final excerpt in excerpts) {
            await txn.insert('book_excerpts', _convertToDbMap(excerpt));
          }
        }

        // 导入标签数据
        if (data.containsKey('tags')) {
          final tags = data['tags'] as List<dynamic>;
          for (final tag in tags) {
            final map = _convertToDbMap(tag);
            await txn.rawInsert(
              'INSERT OR IGNORE INTO tags (id, name, type, created_at) VALUES (?, ?, ?, ?)',
              [map['id'], map['name'], map['type'], map['created_at']],
            );
          }
        }
      });

      // 恢复用户个人信息
      if (backupData.containsKey('userInfo')) {
        final userInfo = backupData['userInfo'] as Map<String, dynamic>;
        final userPrefs = UserPrefs();
        
        if (userInfo.containsKey('nickname')) {
          await userPrefs.setNickname(userInfo['nickname'] as String);
        }
        if (userInfo.containsKey('motto')) {
          await userPrefs.setMotto(userInfo['motto'] as String);
        }
        if (userInfo.containsKey('avatarPath')) {
          final avatarPath = userInfo['avatarPath'] as String?;
          if (avatarPath != null && avatarPath.isNotEmpty) {
            // 更新头像路径为新的路径
            final fileName = path.basename(avatarPath);
            if (imagePathMap.containsKey(fileName)) {
              await userPrefs.setAvatarPath(imagePathMap[fileName]!);
            }
          }
        }
      }
      
      // 统计导入数量
      final stats = <String, int>{};
      if (data.containsKey('movies')) {
        stats['影视'] = (data['movies'] as List).length;
      }
      if (data.containsKey('books')) {
        stats['书籍'] = (data['books'] as List).length;
      }
      if (data.containsKey('notes')) {
        stats['笔记'] = (data['notes'] as List).length;
      }
      if (data.containsKey('movie_reviews')) {
        stats['影评'] = (data['movie_reviews'] as List).length;
      }
      if (data.containsKey('movie_posters')) {
        stats['海报'] = (data['movie_posters'] as List).length;
      }
      if (data.containsKey('tags')) {
        stats['标签'] = (data['tags'] as List).length;
      }
      if (imageCount > 0) {
        stats['图片'] = imageCount;
      }
      
      return ImportResult.success(stats);
    } catch (e) {
      return ImportResult.error('导入失败: $e');
    }
  }
  
  /// 从 ZIP 字节数据恢复（供 WebDAV 同步等场景使用）
  Future<ImportResult> restoreFromZipBytes(Uint8List zipBytes) async {
    try {
      final archive = ZipDecoder().decodeBytes(zipBytes);

      // 查找 data.json
      final dataFile = archive.findFile('data.json');
      if (dataFile == null) {
        return ImportResult.error('备份文件中没有找到数据文件');
      }

      final jsonString = utf8.decode(dataFile.content as List<int>);
      final backupData = jsonDecode(jsonString) as Map<String, dynamic>;

      // 记录图片文件名到新路径的映射
      final imagePathMap = <String, String>{};
      int imageCount = 0;

      // 解压图片到应用目录，保持目录结构
      final appDir = await getApplicationDocumentsDirectory();
      final imagesDir = Directory(path.join(appDir.path, 'images'));
      if (!await imagesDir.exists()) {
        await imagesDir.create(recursive: true);
      }

      for (final archiveFile in archive) {
        if (archiveFile.name.startsWith('images/')) {
          final relativePath = archiveFile.name.substring(7); // 去掉 'images/' 前缀
          final outputFile = File(path.join(imagesDir.path, relativePath));
          final parentDir = outputFile.parent;
          if (!await parentDir.exists()) {
            await parentDir.create(recursive: true);
          }
          await outputFile.writeAsBytes(archiveFile.content as List<int>);
          final fileName = path.basename(archiveFile.name);
          imagePathMap[fileName] = outputFile.path;
          imageCount++;
        }
      }

      // 验证备份格式
      if (!backupData.containsKey('data')) {
        return ImportResult.error('无效的备份文件格式');
      }

      // 导入数据
      final data = backupData['data'] as Map<String, dynamic>;
      final db = await DatabaseHelper.instance.database;

      await db.transaction((txn) async {
        // 清空现有数据
        await txn.delete('movie_reviews');
        await txn.delete('movie_posters');
        await txn.delete('book_reviews');
        await txn.delete('book_excerpts');
        await txn.delete('movies');
        await txn.delete('books');
        await txn.delete('notes');

        if (data.containsKey('movies')) {
          final movies = data['movies'] as List<dynamic>;
          for (final movie in movies) {
            final movieMap = _convertToDbMap(movie);
            final updatedMap = _updateImagePath(movieMap, 'poster_path', imagePathMap);
            await txn.insert('movies', updatedMap);
          }
        }

        if (data.containsKey('books')) {
          final books = data['books'] as List<dynamic>;
          for (final book in books) {
            final bookMap = _convertToDbMap(book);
            final updatedMap = _updateImagePath(bookMap, 'cover_path', imagePathMap);
            await txn.insert('books', updatedMap);
          }
        }

        if (data.containsKey('notes')) {
          final notes = data['notes'] as List<dynamic>;
          for (final note in notes) {
            final noteMap = _convertToDbMap(note);
            final updatedMap = _updateNoteImagesPath(noteMap, imagePathMap);
            await txn.insert('notes', updatedMap);
          }
        }

        if (data.containsKey('movie_reviews')) {
          final reviews = data['movie_reviews'] as List<dynamic>;
          for (final review in reviews) {
            await txn.insert('movie_reviews', _convertToDbMap(review));
          }
        }

        if (data.containsKey('movie_posters')) {
          final posters = data['movie_posters'] as List<dynamic>;
          for (final poster in posters) {
            final posterMap = _convertToDbMap(poster);
            final updatedMap = _updateImagePath(posterMap, 'poster_path', imagePathMap);
            await txn.insert('movie_posters', updatedMap);
          }
        }
        // 导入书评数据
        if (data.containsKey('book_reviews')) {
          final reviews = data['book_reviews'] as List<dynamic>;
          for (final review in reviews) {
            await txn.insert('book_reviews', _convertToDbMap(review));
          }
        }
        // 导入书摘数据
        if (data.containsKey('book_excerpts')) {
          final excerpts = data['book_excerpts'] as List<dynamic>;
          for (final excerpt in excerpts) {
            await txn.insert('book_excerpts', _convertToDbMap(excerpt));
          }
        }

        // 导入标签数据
        if (data.containsKey('tags')) {
          final tags = data['tags'] as List<dynamic>;
          for (final tag in tags) {
            final map = _convertToDbMap(tag);
            await txn.rawInsert(
              'INSERT OR IGNORE INTO tags (id, name, type, created_at) VALUES (?, ?, ?, ?)',
              [map['id'], map['name'], map['type'], map['created_at']],
            );
          }
        }
      });

      // 恢复用户个人信息
      if (backupData.containsKey('userInfo')) {
        final userInfo = backupData['userInfo'] as Map<String, dynamic>;
        final userPrefs = UserPrefs();

        if (userInfo.containsKey('nickname')) {
          await userPrefs.setNickname(userInfo['nickname'] as String);
        }
        if (userInfo.containsKey('motto')) {
          await userPrefs.setMotto(userInfo['motto'] as String);
        }
        if (userInfo.containsKey('avatarPath')) {
          final avatarPath = userInfo['avatarPath'] as String?;
          if (avatarPath != null && avatarPath.isNotEmpty) {
            final fileName = path.basename(avatarPath);
            if (imagePathMap.containsKey(fileName)) {
              await userPrefs.setAvatarPath(imagePathMap[fileName]!);
            }
          }
        }
      }

      // 统计导入数量
      final stats = <String, int>{};
      if (data.containsKey('movies')) stats['影视'] = (data['movies'] as List).length;
      if (data.containsKey('books')) stats['书籍'] = (data['books'] as List).length;
      if (data.containsKey('notes')) stats['笔记'] = (data['notes'] as List).length;
      if (data.containsKey('movie_reviews')) stats['影评'] = (data['movie_reviews'] as List).length;
      if (data.containsKey('movie_posters')) stats['海报'] = (data['movie_posters'] as List).length;
      if (data.containsKey('book_reviews')) stats['书评'] = (data['book_reviews'] as List).length;
      if (data.containsKey('book_excerpts')) stats['书摘'] = (data['book_excerpts'] as List).length;
      if (imageCount > 0) stats['图片'] = imageCount;

      return ImportResult.success(stats);
    } catch (e) {
      return ImportResult.error('恢复失败: $e');
    }
  }

  /// 将动态类型转换为数据库可用的 Map
  Map<String, dynamic> _convertToDbMap(dynamic item) {
    if (item is Map<String, dynamic>) {
      return item.map((key, value) {
        // 处理布尔值
        if (value is bool) {
          return MapEntry(key, value ? 1 : 0);
        }
        return MapEntry(key, value);
      });
    }
    return {};
  }
  
  /// 更新图片路径为新的路径
  /// 支持新的存储结构：images/movies/{id}/、images/books/{id}/、images/notes/{id}/
  Map<String, dynamic> _updateImagePath(
    Map<String, dynamic> item,
    String pathField,
    Map<String, String> imagePathMap,
  ) {
    final newItem = Map<String, dynamic>.from(item);
    final oldPath = item[pathField] as String?;
    
    if (oldPath != null && oldPath.isNotEmpty) {
      final fileName = path.basename(oldPath);
      // 如果图片在映射中，更新路径
      if (imagePathMap.containsKey(fileName)) {
        newItem[pathField] = imagePathMap[fileName];
      } else {
        // 尝试从旧版备份中恢复（旧版只保存了文件名）
        // 检查是否有匹配的文件名（不区分目录结构）
        for (final entry in imagePathMap.entries) {
          if (path.basename(entry.key) == fileName) {
            newItem[pathField] = entry.value;
            break;
          }
        }
      }
    }
    
    return newItem;
  }
  
  /// 更新笔记图片路径为新的路径
  /// 支持新的存储结构：images/notes/{id}/
  Map<String, dynamic> _updateNoteImagesPath(
    Map<String, dynamic> item,
    Map<String, String> imagePathMap,
  ) {
    final newItem = Map<String, dynamic>.from(item);
    final imagesJson = item['images'] as String?;
    
    if (imagesJson != null && imagesJson.isNotEmpty) {
      try {
        final images = jsonDecode(imagesJson) as List<dynamic>;
        final updatedImages = <String>[];
        
        for (final imagePath in images) {
          if (imagePath is String && imagePath.isNotEmpty) {
            final fileName = path.basename(imagePath);
            // 如果图片在映射中，更新路径
            if (imagePathMap.containsKey(fileName)) {
              updatedImages.add(imagePathMap[fileName]!);
            } else {
              // 尝试从旧版备份中恢复（旧版只保存了文件名）
              bool found = false;
              for (final entry in imagePathMap.entries) {
                if (path.basename(entry.key) == fileName) {
                  updatedImages.add(entry.value);
                  found = true;
                  break;
                }
              }
              if (!found) {
                updatedImages.add(imagePath);
              }
            }
          }
        }
        
        newItem['images'] = jsonEncode(updatedImages);
      } catch (e) {
        // 解析失败，保持原样
      }
    }
    
    return newItem;
  }
  
  /// 格式化日期时间用于文件名
  String _formatDateTime(DateTime dateTime) {
    return '${dateTime.year}${_pad(dateTime.month)}${_pad(dateTime.day)}_${_pad(dateTime.hour)}${_pad(dateTime.minute)}${_pad(dateTime.second)}';
  }
  
  String _pad(int number) {
    return number.toString().padLeft(2, '0');
  }
}

/// 自动备份导出结果
class AutoBackupExportResult {
  final bool success;
  final String? errorMessage;
  final Uint8List? zipBytes;
  final int movieCount;
  final int bookCount;
  final int noteCount;
  final int imageCount;
  
  AutoBackupExportResult._({
    required this.success,
    this.errorMessage,
    this.zipBytes,
    this.movieCount = 0,
    this.bookCount = 0,
    this.noteCount = 0,
    this.imageCount = 0,
  });
  
  factory AutoBackupExportResult.success({
    required Uint8List zipBytes,
    required int movieCount,
    required int bookCount,
    required int noteCount,
    required int imageCount,
  }) {
    return AutoBackupExportResult._(
      success: true,
      zipBytes: zipBytes,
      movieCount: movieCount,
      bookCount: bookCount,
      noteCount: noteCount,
      imageCount: imageCount,
    );
  }
  
  factory AutoBackupExportResult.error(String message) {
    return AutoBackupExportResult._(success: false, errorMessage: message);
  }
}

/// 导出结果
class ExportResult {
  final bool success;
  final bool cancelled;
  final String? errorMessage;
  final String? filePath;
  final int movieCount;
  final int bookCount;
  final int noteCount;
  final int imageCount;
  
  ExportResult._({
    required this.success,
    this.cancelled = false,
    this.errorMessage,
    this.filePath,
    this.movieCount = 0,
    this.bookCount = 0,
    this.noteCount = 0,
    this.imageCount = 0,
  });
  
  factory ExportResult.success({
    required String filePath,
    required int movieCount,
    required int bookCount,
    required int noteCount,
    required int imageCount,
  }) {
    return ExportResult._(
      success: true,
      filePath: filePath,
      movieCount: movieCount,
      bookCount: bookCount,
      noteCount: noteCount,
      imageCount: imageCount,
    );
  }
  
  factory ExportResult.cancelled() {
    return ExportResult._(success: false, cancelled: true);
  }
  
  factory ExportResult.error(String message) {
    return ExportResult._(success: false, errorMessage: message);
  }
}

/// 导入结果
class ImportResult {
  final bool success;
  final bool cancelled;
  final String? errorMessage;
  final Map<String, int>? stats;
  
  ImportResult._({
    required this.success,
    this.cancelled = false,
    this.errorMessage,
    this.stats,
  });
  
  factory ImportResult.success(Map<String, int> stats) {
    return ImportResult._(success: true, stats: stats);
  }
  
  factory ImportResult.cancelled() {
    return ImportResult._(success: false, cancelled: true);
  }
  
  factory ImportResult.error(String message) {
    return ImportResult._(success: false, errorMessage: message);
  }
  
  /// 获取统计信息文本
  String get statsText {
    if (stats == null || stats!.isEmpty) {
      return '没有导入任何数据';
    }
    return stats!.entries.map((e) => '${e.key}: ${e.value}').join('，');
  }
}
