import 'dart:io';
import 'dart:async';
import 'dart:developer' as developer;
import 'dart:collection';
import 'package:path_provider/path_provider.dart';

import '../../app/constants/configs.dart';
import '../developer/ix_developer_tools.dart';

/// 日志条目
class LogEntry {
  final DateTime timestamp;
  final String message;
  final String name;

  LogEntry(this.timestamp, this.message, this.name);

  @override
  String toString() {
    return '[${timestamp.toIso8601String()}] $name $message';
  }
}

/// 优化的日志管理器
/// 特性：
/// 1. 使用队列批量写入，避免频繁文件操作
/// 2. 按日期分文件存储
/// 3. 自动清理7天前的日志
/// 4. 异步处理，不阻塞主线程
class LogManager {
  static final LogManager _instance = LogManager._internal();

  // 单例模式
  factory LogManager() => _instance;
  LogManager._internal();

  // 配置常量
  static const int _maxLogFileSize = 5 * 1024 * 1024; // 5MB per file
  static const int _batchWriteSize = 50; // 批量写入条数
  static const Duration _batchWriteInterval = Duration(seconds: 5); // 批量写入间隔
  static const int _retentionDays = 7; // 保留天数
  static const int _maxQueueSize = 1000; // 队列最大大小

  // 状态变量
  bool _isInitialized = false;
  late Directory _logDirectory;
  final Queue<LogEntry> _logQueue = Queue<LogEntry>();
  Timer? _batchWriteTimer;
  bool _isWriting = false;

  /// 初始化日志管理器
  Future<void> init() async {
    if (_isInitialized) return;

    try {
      // 获取日志存储目录
      final appDir = await getApplicationDocumentsDirectory();
      _logDirectory = Directory('${appDir.path}/logs');

      // 创建日志目录
      if (!await _logDirectory.exists()) {
        await _logDirectory.create(recursive: true);
      }

      // 清理过期日志文件
      await _cleanupOldLogs();

      // 启动批量写入定时器
      _startBatchWriteTimer();

      _isInitialized = true;
    } catch (e) {
      print('Failed to initialize LogManager: $e');
      rethrow;
    }
  }

  /// 启动批量写入定时器
  void _startBatchWriteTimer() {
    _batchWriteTimer?.cancel();
    _batchWriteTimer = Timer.periodic(_batchWriteInterval, (_) {
      _flushLogs();
    });
  }

  /// 添加日志到队列
  void _addToQueue(String message, String name) {
    final entry = LogEntry(DateTime.now(), message, name);
    _logQueue.add(entry);

    // 如果队列满了，立即写入
    if (_logQueue.length >= _maxQueueSize) {
      _flushLogs();
    }
  }

  /// 批量写入日志
  Future<void> _flushLogs() async {
    if (_isWriting || _logQueue.isEmpty) return;

    _isWriting = true;
    try {
      final logsToWrite = <LogEntry>[];

      // 取出要写入的日志条目
      final count = _logQueue.length > _batchWriteSize
          ? _batchWriteSize
          : _logQueue.length;
      for (int i = 0; i < count; i++) {
        logsToWrite.add(_logQueue.removeFirst());
      }

      if (logsToWrite.isNotEmpty) {
        await _writeLogsToFile(logsToWrite);
      }
    } catch (e) {
      print('Failed to flush logs: $e');
    } finally {
      _isWriting = false;
    }
  }

  /// 写入日志到文件
  Future<void> _writeLogsToFile(List<LogEntry> logs) async {
    try {
      // 按日期分组
      final logsByDate = <String, List<LogEntry>>{};
      for (final log in logs) {
        final dateKey = _getDateKey(log.timestamp);
        logsByDate.putIfAbsent(dateKey, () => []).add(log);
      }

      // 写入到对应的日期文件
      for (final entry in logsByDate.entries) {
        final dateKey = entry.key;
        final dateLogs = entry.value;
        await _writeToDateFile(dateKey, dateLogs);
      }
    } catch (e) {
      print('Failed to write logs to file: $e');
    }
  }

  /// 写入到指定日期的文件
  Future<void> _writeToDateFile(String dateKey, List<LogEntry> logs) async {
    try {
      final logFile = File('${_logDirectory.path}/log_$dateKey.txt');

      // 检查文件大小
      if (await logFile.exists()) {
        final fileSize = await logFile.length();
        if (fileSize > _maxLogFileSize) {
          // 文件过大，截断保留最新内容
          await _truncateLogFile(logFile);
        }
      }

      // 写入日志
      final logContent = '${logs.map((log) => log.toString()).join('\n')}\n';
      await logFile.writeAsString(logContent, mode: FileMode.append);
    } catch (e) {
      print('Failed to write to date file: $e');
    }
  }

  /// 截断日志文件，保留最新内容
  Future<void> _truncateLogFile(File logFile) async {
    try {
      final content = await logFile.readAsString();
      final lines = content.split('\n');

      // 保留最后一半的内容
      final keepLines = (lines.length / 2).floor();
      final newContent =
          '${lines.sublist(lines.length - keepLines).join('\n')}\n';

      await logFile.writeAsString(newContent);
    } catch (e) {
      print('Failed to truncate log file: $e');
      // 如果截断失败，重新创建文件
      await logFile.writeAsString('');
    }
  }

  /// 获取日期键值
  String _getDateKey(DateTime date) {
    return '${date.year.toString().padLeft(4, '0')}'
        '${date.month.toString().padLeft(2, '0')}'
        '${date.day.toString().padLeft(2, '0')}';
  }

  /// 清理过期日志文件
  Future<void> _cleanupOldLogs() async {
    try {
      final cutoffDate = DateTime.now().subtract(
        const Duration(days: _retentionDays),
      );
      final cutoffDateKey = _getDateKey(cutoffDate);

      final files = await _logDirectory.list().toList();
      for (final file in files) {
        if (file is File && file.path.contains('log_')) {
          final fileName = file.path.split('/').last;
          final dateStr = fileName
              .replaceAll('log_', '')
              .replaceAll('.txt', '');

          if (dateStr.compareTo(cutoffDateKey) < 0) {
            await file.delete();
          }
        }
      }
    } catch (e) {
      print('Failed to cleanup old logs: $e');
    }
  }

  /// 读取指定日期的日志
  Future<String> readLogsForDate(DateTime date) async {
    if (!_isInitialized) {
      await init();
    }

    try {
      final dateKey = _getDateKey(date);
      final logFile = File('${_logDirectory.path}/log_$dateKey.txt');

      if (await logFile.exists()) {
        return await logFile.readAsString();
      }
      return '';
    } catch (e) {
      print('Failed to read logs for date: $e');
      return '';
    }
  }

  /// 读取最近几天的日志
  Future<String> readRecentLogs(int days) async {
    if (!_isInitialized) {
      await init();
    }

    try {
      final allLogs = <String>[];
      final now = DateTime.now();

      for (int i = 0; i < days; i++) {
        final date = now.subtract(Duration(days: i));
        final dateLogs = await readLogsForDate(date);
        if (dateLogs.isNotEmpty) {
          allLogs.add(
            '=== ${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')} ===\n$dateLogs',
          );
        }
      }

      return allLogs.join('\n');
    } catch (e) {
      print('Failed to read recent logs: $e');
      return '';
    }
  }

  /// 读取所有日志
  Future<String> readAllLogs() async {
    return await readRecentLogs(_retentionDays);
  }

  /// 清空所有日志
  Future<void> clearAllLogs() async {
    if (!_isInitialized) {
      await init();
    }

    try {
      // 清空队列
      _logQueue.clear();

      // 删除所有日志文件
      final files = await _logDirectory.list().toList();
      for (final file in files) {
        if (file is File && file.path.contains('log_')) {
          await file.delete();
        }
      }
    } catch (e) {
      print('Failed to clear all logs: $e');
    }
  }

  /// 强制刷新所有待写入的日志
  Future<void> forceFlush() async {
    await _flushLogs();
  }

  /// 销毁日志管理器
  Future<void> dispose() async {
    _batchWriteTimer?.cancel();
    await _flushLogs();
    _isInitialized = false;
  }

  /// 静态日志方法
  static void log(String message, String name) {
    if (Configs.debug) {
      developer.log(message, name: name);
    }
    _instance._addToQueue(message, name);
    // 添加到简化版开发者工具
    IXDeveloperTools.addLog(message, name);
  }
}
