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

import 'package:connectivity_plus/connectivity_plus.dart';

import 'package:flutter_dmzj/app/log.dart';
import 'package:flutter_dmzj/models/db/novel_download_info.dart';
import 'package:flutter_dmzj/models/db/download_status.dart';
import 'package:flutter_dmzj/models/novel/novel_detail_model.dart';

import 'package:flutter_dmzj/services/app_settings_service.dart';
import 'package:flutter_dmzj/services/download_task/novel_downloader.dart';
import 'package:get/get.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
// ignore: depend_on_referenced_packages
import 'package:collection/collection.dart';
// ignore: depend_on_referenced_packages
import 'package:path/path.dart' as p;

/// 小说下载管理
// TODO 整理代码
class NovelDownloadService extends GetxService {
  static NovelDownloadService get instance => Get.find<NovelDownloadService>();

  AppSettingsService settings = AppSettingsService.instance;

  late Box<NovelDownloadInfo> box;
  String savePath = "";

  /// 连接信息监听
  StreamSubscription<ConnectivityResult>? connectivitySubscription;

  /// 当前连接类型
  ConnectivityResult? connectivityType;

  /// 当前正在下载的数量
  var currentNum = 0;

  Future init() async {
    var dir = await getApplicationSupportDirectory();
    box = await Hive.openBox(
      "NovelDownload",
      path: dir.path,
    );
    savePath = await getSavePath();
    //监听网络状态
    initConnectivity();
    //更新ID
    updateAllIds();

    updateDownlaoded();
  }

  /// 初始化连接状态
  void initConnectivity() async {
    try {
      var connectivity = Connectivity();
      connectivitySubscription = connectivity.onConnectivityChanged
          .listen((ConnectivityResult result) {
        networkChanged(result);
      });
      connectivityType = await connectivity.checkConnectivity();
      initTasks();
    } catch (e) {
      Log.logPrint(e);
      initTasks();
    }
  }

  /// 网络变更
  void networkChanged(ConnectivityResult type) {
    if (connectivityType != type && type == ConnectivityResult.mobile) {
      //切换至流量
      switchCellular();
    } else if (connectivityType != type && type == ConnectivityResult.none) {
      //网络断开
      switchNoNetwork();
    } else {
      switchToWiFi();
    }
    connectivityType = type;
  }

  /// 切换至流量
  void switchCellular() {
    if (settings.downloadAllowCellular.value) {
      //允许使用流量,当成WiFi处理
      switchToWiFi();
      return;
    }
    //把任务状态改为pauseCellular
    for (var item in taskQueues) {
      if (item.status == DownloadStatus.wait ||
          item.status == DownloadStatus.loadding ||
          item.status == DownloadStatus.downloading ||
          item.status == DownloadStatus.waitNetwork) {
        item.stopTask();
        item.updateStatus(DownloadStatus.pauseCellular, updateTask: false);
      }
    }
    updateQueue();
  }

  /// 无网络
  void switchNoNetwork() {
    //把任务状态改为pauseCellular
    for (var item in taskQueues) {
      if (item.status == DownloadStatus.wait ||
          item.status == DownloadStatus.loadding ||
          item.status == DownloadStatus.downloading ||
          item.status == DownloadStatus.pauseCellular) {
        item.stopTask();
        item.updateStatus(DownloadStatus.waitNetwork, updateTask: false);
      }
    }
    updateQueue();
  }

  void switchToWiFi() {
    for (var item in taskQueues) {
      if (item.status == DownloadStatus.pauseCellular ||
          item.status == DownloadStatus.waitNetwork) {
        item.updateStatus(DownloadStatus.wait, updateTask: false);
      }
    }
    updateQueue();
  }

  /// 任务列表
  RxList<NovelDownloader> taskQueues = RxList<NovelDownloader>();

  /// 已下载完成的
  RxList<NovelDownloadedItem> downloaded = RxList<NovelDownloadedItem>();

  /// 已下载、下载中的ID
  RxSet<String> downloadIds = RxSet<String>();

  /// 开始下载任务
  void initTasks() async {
    var tasks = getDownloadingTask();
    for (var item in tasks) {
      //任务已被取消
      if (item.status == DownloadStatus.cancel) {
        box.delete(item.taskId);
        continue;
      }
      //无网络
      if (connectivityType == ConnectivityResult.none) {
        if (item.status != DownloadStatus.pause) {
          item.status = DownloadStatus.waitNetwork;
        }
      } else if (connectivityType == ConnectivityResult.mobile) {
        //不允许使用数据下载
        if (!settings.downloadAllowCellular.value) {
          if (item.status != DownloadStatus.pause) {
            item.status = DownloadStatus.pauseCellular;
          }
        }
      } else {
        //只要不是手动暂停的，全部改为等待，添加到下载队列
        if (item.status != DownloadStatus.pause) {
          item.status = DownloadStatus.wait;
        }
      }

      taskQueues.add(
        NovelDownloader(item, onUpdateTask: onUpdateTask),
      );
    }
    updateQueue();
  }

  /// 更新队列
  void updateQueue() {
    //如果下载中任务数小于设定值，添加一个任务
    //如果任务取消或完成，移除队列
    for (var task in List<NovelDownloader>.from(taskQueues)) {
      //下载完成或取消，移除队列
      if (task.status == DownloadStatus.complete ||
          task.status == DownloadStatus.cancel) {
        taskQueues.remove(task);
        updateDownlaoded();
        continue;
      }
    }
    var taskNum = settings.downloadNovelTaskCount.value;
    var count = taskQueues
        .where((x) =>
            x.status == DownloadStatus.downloading ||
            x.status == DownloadStatus.loadding)
        .length;

    currentNum = count;
    if (taskNum == 0) {
      var ls = taskQueues.where((x) => x.status == DownloadStatus.wait);
      for (var item in ls) {
        item.start();
      }
    } else {
      if (count < taskNum) {
        var ls = taskQueues
            .where((x) => x.status == DownloadStatus.wait)
            .take(taskNum - count)
            .toList();
        for (var item in ls) {
          item.start();
        }
      }
    }
    updateAllIds();
  }

  void updateAllIds() {
    downloadIds.clear();
    downloadIds.addAll(box.keys.map((e) => e.toString()));
  }

  ///读取未完成的任务
  List<NovelDownloadInfo> getDownloadingTask() {
    return box.values
        .toList()
        .where((x) => x.status != DownloadStatus.complete)
        .toList();
  }

  /// 更新下载完成
  void updateDownlaoded() {
    var downlaodedList = box.values
        .toList()
        .where((x) => x.status == DownloadStatus.complete)
        .toList();
    var novelMap = groupBy(downlaodedList, (NovelDownloadInfo x) => x.novelId);
    List<NovelDownloadedItem> novelList = [];
    for (var novelId in novelMap.keys) {
      var items = novelMap[novelId]!;
      var novelName = items.first.novelName;
      var novelCover = items.first.novelCover;

      List<NovelDetailVolume> volumes = [];
      var volumeMap = groupBy(items, (NovelDownloadInfo x) => x.volumeID);
      for (var volumeID in volumeMap.keys) {
        var chapters = volumeMap[volumeID]!
            .map(
              (e) => NovelDetailChapter(
                chapterId: e.chapterId,
                chapterName: e.chapterName,
                volumeId: e.volumeID,
                volumeName: e.volumeName,
                volumeOrder: e.volumeOrder,
                chapterOrder: e.chapterSort,
              ),
            )
            .toList();
        chapters.sort((a, b) => a.chapterOrder.compareTo(b.chapterOrder));
        volumes.add(
          NovelDetailVolume(
            volumeName: chapters.first.volumeName,
            volumeId: chapters.first.volumeId,
            volumeOrder: chapters.first.volumeOrder,
            chapters: chapters,
          ),
        );
      }
      volumes.sort((a, b) => a.volumeOrder.compareTo(b.volumeOrder));
      novelList.add(
        NovelDownloadedItem(
          novelName: novelName,
          novelCover: novelCover,
          novelId: novelId,
          chapterCount: items.length,
          volumes: volumes,
        ),
      );
    }
    downloaded.value = novelList;
  }

  /// 继续
  void resumeAll() {
    //更新状态至等待
    for (var task in taskQueues) {
      if (task.status == DownloadStatus.pause) {
        task.stopTask();
        task.updateStatus(DownloadStatus.wait, updateTask: false);
      }
    }
    updateQueue();
  }

  /// 暂停
  void pauseAll() {
    for (var task in taskQueues) {
      if (task.status != DownloadStatus.pause &&
          task.status != DownloadStatus.error &&
          task.status != DownloadStatus.errorLoad) {
        task.stopTask();
        task.updateStatus(DownloadStatus.pause, updateTask: false);
      }
    }
    updateQueue();
  }

  /// 添加一个任务
  void addTask({
    required int novelId,
    required int chapterId,
    required String chapterName,
    required int chapterSort,
    required int volumeId,
    required int volumeOrder,
    required String volumeName,
    required String novelTitle,
    required String novelCover,
    required bool isVip,
  }) async {
    var taskId = "${novelId}_${volumeId}_$chapterId";
    if (box.containsKey(taskId)) {
      return;
    }
    var info = NovelDownloadInfo(
      addTime: DateTime.now(),
      chapterId: chapterId,
      chapterSort: chapterSort,
      novelCover: novelCover,
      novelId: novelId,
      novelName: novelTitle,
      savePath: p.join(savePath, taskId),
      status: DownloadStatus.wait,
      taskId: taskId,
      volumeName: volumeName,
      chapterName: chapterName,
      isVip: isVip,
      progress: 0,
      fileName: '',
      imageFiles: [],
      isImage: false,
      volumeID: volumeId,
      volumeOrder: volumeOrder,
      imageUrls: [],
    );
    await box.put(
      taskId,
      info,
    );
    taskQueues.add(NovelDownloader(info, onUpdateTask: onUpdateTask));
    updateQueue();
  }

  void onUpdateTask() {
    updateQueue();
  }

  /// 读取保存目录
  Future<String> getSavePath() async {
    var dir = await getApplicationSupportDirectory();

    var novelDir = Directory(p.join(dir.path, "novel"));
    if (!await novelDir.exists()) {
      novelDir = await novelDir.create(recursive: true);
    }
    return novelDir.path;
  }

  ///删除
  void delete(NovelDownloadInfo info) async {
    try {
      var dir = Directory(p.join(savePath, info.taskId));
      await dir.delete(recursive: true);
    } catch (e) {
      Log.logPrint(e);
    } finally {
      await box.delete(info.taskId);
      updateDownlaoded();
    }
    updateAllIds();
  }

  ///删除
  void deleteChapter(int novelId, int volumeId, int chapterId) async {
    var info = box.get("${novelId}_${volumeId}_$chapterId");
    if (info != null) {
      delete(info);
    }
  }
}

class NovelDownloadedItem {
  final String novelName;
  final int novelId;
  final String novelCover;
  final List<NovelDetailVolume> volumes;
  final int chapterCount;
  NovelDownloadedItem({
    required this.novelName,
    required this.novelCover,
    required this.novelId,
    required this.chapterCount,
    required this.volumes,
  });
}
