import 'dart:io';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:http/http.dart' as http;

/// 更新服务 - 处理版本检查和客户端更新
class UpdateService {
  static final UpdateService _instance = UpdateService._internal();
  factory UpdateService() => _instance;
  UpdateService._internal();

  final Logger _logger = Logger('UpdateService');

  /// 检查远程版本信息
  Future<RemoteVersionInfo?> checkVersion(String updateUrl) async {
    try {
      _logger.info('检查远程版本: $updateUrl');
      
      // 构建版本检查URL: update_url/user/getClientVersion
      final versionUrl = updateUrl.endsWith('/') 
          ? '${updateUrl}user/getClientVersion'
          : '$updateUrl/user/getClientVersion';
      
      final response = await http.get(Uri.parse(versionUrl)).timeout(
        const Duration(seconds: 10),
      );

      if (response.statusCode == 200) {
        // 返回的是纯文本版本号，不是JSON
        final remoteVersion = response.body.trim();
        
        if (remoteVersion.isEmpty) {
          _logger.warning('远程版本号为空');
          return null;
        }
        
        _logger.info('获取到远程版本号: $remoteVersion');
        
        // 注意：这里只返回版本号，下载URL需要从其他地方获取
        // 可以根据需要扩展 RemoteVersionInfo 或使用其他方式获取下载URL
        return RemoteVersionInfo(
          version: remoteVersion,
          downloadUrl: '', // 需要从其他接口获取或使用默认URL
          releaseNotes: null,
        );
      } else {
        _logger.warning('获取版本信息失败: HTTP ${response.statusCode}');
      }
    } catch (e) {
      _logger.warning('检查版本失败: $e');
    }
    return null;
  }

  /// 比较版本号（简单字符串比较，可以改进为语义化版本比较）
  bool isNewerVersion(String remoteVersion, String localVersion) {
    // 简单的字符串比较，如果不同则认为远程版本更新
    // 可以改进为语义化版本比较（如 1.2.3 vs 1.2.4）
    return remoteVersion != localVersion && remoteVersion.isNotEmpty;
  }

  /// 下载并更新客户端
  Future<bool> downloadAndUpdate(String downloadUrl) async {
    try {
      _logger.info('开始下载新版本: $downloadUrl');
      
      // 获取当前可执行文件路径
      final currentExe = Platform.resolvedExecutable;
      final exeDir = p.dirname(currentExe);
      final exeName = p.basename(currentExe);
      
      // 下载文件保存为临时文件
      final tempFile = p.join(exeDir, '${exeName}.new');
      final backupFile = p.join(exeDir, '${exeName}.backup');
      
      // 下载文件
      final response = await http.get(Uri.parse(downloadUrl)).timeout(
        const Duration(minutes: 10),
      );

      if (response.statusCode != 200) {
        _logger.severe('下载失败: HTTP ${response.statusCode}');
        return false;
      }

      // 保存到临时文件
      final file = File(tempFile);
      await file.writeAsBytes(response.bodyBytes);
      _logger.info('文件下载完成: $tempFile');

      // 备份当前文件
      final currentFile = File(currentExe);
      if (await currentFile.exists()) {
        await currentFile.copy(backupFile);
        _logger.info('已备份当前文件: $backupFile');
      }

      // 替换文件（需要关闭当前进程）
      // 注意：在 Windows 上，不能直接覆盖正在运行的可执行文件
      // 需要使用批处理脚本在下次启动时替换
      await _createUpdateScript(exeDir, exeName, tempFile, backupFile);
      
      _logger.info('更新脚本已创建，将在下次启动时应用更新');
      return true;
    } catch (e) {
      _logger.severe('下载更新失败: $e');
      return false;
    }
  }

  /// 创建更新脚本（Windows批处理文件）
  Future<void> _createUpdateScript(
    String exeDir,
    String exeName,
    String tempFile,
    String backupFile,
  ) async {
    final scriptPath = p.join(exeDir, 'update.bat');
    final script = '''
@echo off
timeout /t 2 /nobreak >nul
copy /Y "$tempFile" "$exeDir\\$exeName"
if %ERRORLEVEL% EQU 0 (
    del "$tempFile"
    echo 更新成功
) else (
    copy /Y "$backupFile" "$exeDir\\$exeName"
    echo 更新失败，已恢复备份
    del "$tempFile"
)
del "$backupFile"
del "%~f0"
''';

    final scriptFile = File(scriptPath);
    await scriptFile.writeAsString(script);
    
    // 执行脚本（延迟执行，以便当前进程退出）
    Process.start('cmd', ['/c', 'start', '/min', scriptPath], runInShell: true);
  }
}

/// 远程版本信息
class RemoteVersionInfo {
  final String version;
  final String downloadUrl;
  final String? releaseNotes;

  RemoteVersionInfo({
    required this.version,
    required this.downloadUrl,
    this.releaseNotes,
  });
}
