import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:logging/logging.dart';

import 'mining_task_info.dart';
import '../utils/path_utils.dart';

/// 挖矿任务持久化服务（基于 .log 文件，而非 SQLite）
///
/// 设计约定：
/// - 使用 `bin/mining_tasks.log` 记录当前（或最近）挖矿任务，一行一条 JSON 记录。
/// - 每次收到新的挖矿任务时，追加一条记录。
/// - 挖矿任务完成后，从 .log 中删除对应记录。
/// - 客户端启动时读取 .log：
///   - 如果存在任务且 `endTimestamp` 尚未过期，则恢复该任务；
///   - 如果已过期，则删除该记录，并不恢复。
class DatabaseService {
  static final DatabaseService _instance = DatabaseService._internal();
  factory DatabaseService() => _instance;
  DatabaseService._internal();

  final Logger _logger = Logger('DatabaseService');

  /// 日志文件路径：bin/mining_tasks.log
  File get _logFile => File(PathUtils.binFile('mining_tasks.log'));

  /// 初始化（确保 bin 目录存在）
  Future<void> initialize() async {
    try {
      // 确保 bin 目录存在
      final binDir = Directory(PathUtils.binDir);
      if (!await binDir.exists()) {
        await binDir.create(recursive: true);
      }

      // 日志文件可懒创建，不强制在这里创建
      _logger.info('任务日志初始化完成（使用文件存储，不再使用 SQLite）');
    } catch (e) {
      _logger.severe('任务日志初始化失败: $e');
      rethrow;
    }
  }

  /// 插入挖矿任务（在 .log 文件中追加一条记录）
  Future<int> insertMiningTask(MiningTaskInfo task) async {
    await initialize();

    try {
      final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
      final record = <String, dynamic>{
        'coin': task.coin,
        'algo': task.algo,
        'pool': task.pool,
        'pool_url': task.poolUrl,
        'wallet_address': task.walletAddress,
        'worker_id': task.workerId,
        'pool_user': task.poolUser,
        'wallet_mining': task.walletMining,
        'end_timestamp': task.endTimestamp,
        'miner': task.miner,
        'created_at': now,
      };

      final jsonLine = jsonEncode(record);
      await _logFile.writeAsString('$jsonLine\n', mode: FileMode.append, flush: true);

      return 1; // 返回值目前未被使用，保持兼容即可
    } catch (e) {
      _logger.severe('插入挖矿任务失败: $e');
      rethrow;
    }
  }

  /// 挖矿任务完成后，从 .log 文件中删除该任务
  Future<void> finishMiningTask(MiningTaskInfo task) async {
    await initialize();

    try {
      if (!await _logFile.exists()) {
        return;
      }

      final lines = await _logFile.readAsLines();
      if (lines.isEmpty) return;

      final List<String> keptLines = [];

      for (final line in lines) {
        if (line.trim().isEmpty) continue;
        try {
          final Map<String, dynamic> data = jsonDecode(line) as Map<String, dynamic>;
          final existing = _taskFromJson(data);

          // 如果与当前任务匹配，则跳过（即删除）
          if (_isSameTask(existing, task)) {
            continue;
          }

          keptLines.add(line);
        } catch (_) {
          // 解析失败的行保留，避免误删
          keptLines.add(line);
        }
      }

      await _logFile.writeAsString(keptLines.join('\n') + (keptLines.isEmpty ? '' : '\n'));
    } catch (e) {
      _logger.severe('完成挖矿任务（从日志中删除）失败: $e');
    }
  }

  /// 加载未完成的挖矿任务
  ///
  /// - 读取 .log 中所有任务；
  /// - 删除已过期（endTimestamp <= now）的任务；
  /// - 返回最新的、尚未过期的任务（如果有）。
  Future<MiningTaskInfo?> loadUnfinishedTask() async {
    await initialize();

    try {
      if (!await _logFile.exists()) {
        return null;
      }

      final lines = await _logFile.readAsLines();
      if (lines.isEmpty) {
        return null;
      }

      final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
      final List<_StoredTask> validTasks = [];

      for (final line in lines) {
        if (line.trim().isEmpty) continue;
        try {
          final Map<String, dynamic> data = jsonDecode(line) as Map<String, dynamic>;
          final task = _taskFromJson(data);
          final createdAt = (data['created_at'] as int?) ?? task.endTimestamp;

          // 过滤掉已过期任务
          if (now >= task.endTimestamp) {
            continue;
          }

          validTasks.add(_StoredTask(task: task, createdAt: createdAt));
        } catch (e) {
          _logger.warning('解析任务日志行失败，已跳过: $e, 原始行: $line');
        }
      }

      // 重新写回仅包含未过期的任务
      if (validTasks.isEmpty) {
        await _logFile.writeAsString('');
        return null;
      } else {
        // 按创建时间排序，取最新一条作为恢复任务
        validTasks.sort((a, b) => b.createdAt.compareTo(a.createdAt));
        final toKeep = validTasks;
        final buffer = StringBuffer();
        for (final t in toKeep) {
          final record = _taskToJson(t.task, createdAt: t.createdAt);
          buffer.writeln(jsonEncode(record));
        }
        await _logFile.writeAsString(buffer.toString());

        return validTasks.first.task;
      }
    } catch (e) {
      _logger.severe('加载挖矿任务失败: $e');
      return null;
    }
  }

  /// 获取任务历史（目前基于 .log 仅保存“当前/最近”任务，这里返回空列表以保持接口兼容）
  Future<List<Map<String, dynamic>>> getTaskHistory({int limit = 100}) async {
    // 如有需要，可以在未来扩展为持久化历史记录
    return [];
  }

  /// 关闭（对文件存储无实际操作，保留接口以兼容旧代码）
  Future<void> close() async {
    // no-op
  }

  // === 内部工具方法 ===

  MiningTaskInfo _taskFromJson(Map<String, dynamic> data) {
    return MiningTaskInfo(
      coin: data['coin'] as String,
      algo: data['algo'] as String,
      pool: (data['pool'] as String?) ?? '',
      poolUrl: data['pool_url'] as String,
      walletAddress: data['wallet_address'] as String,
      workerId: data['worker_id'] as String,
      poolUser: data['pool_user'] as String?,
      walletMining: (data['wallet_mining'] as bool?) ??
          ((data['wallet_mining'] is int) ? (data['wallet_mining'] as int) == 1 : false),
      endTimestamp: data['end_timestamp'] as int,
      miner: data['miner'] as String,
    );
  }

  Map<String, dynamic> _taskToJson(MiningTaskInfo task, {required int createdAt}) {
    return <String, dynamic>{
      'coin': task.coin,
      'algo': task.algo,
      'pool': task.pool,
      'pool_url': task.poolUrl,
      'wallet_address': task.walletAddress,
      'worker_id': task.workerId,
      'pool_user': task.poolUser,
      'wallet_mining': task.walletMining,
      'end_timestamp': task.endTimestamp,
      'miner': task.miner,
      'created_at': createdAt,
    };
  }

  bool _isSameTask(MiningTaskInfo a, MiningTaskInfo b) {
    return a.coin == b.coin &&
        a.algo == b.algo &&
        a.pool == b.pool &&
        a.poolUrl == b.poolUrl &&
        a.walletAddress == b.walletAddress &&
        a.workerId == b.workerId &&
        (a.poolUser ?? '') == (b.poolUser ?? '') &&
        a.walletMining == b.walletMining &&
        a.endTimestamp == b.endTimestamp &&
        a.miner == b.miner;
  }
}

class _StoredTask {
  final MiningTaskInfo task;
  final int createdAt;

  _StoredTask({required this.task, required this.createdAt});
}
