import 'dart:async';

import 'package:electronic_assistant/base/base_controller.dart';
import 'package:electronic_assistant/data/consts/event_report_id.dart';
import 'package:electronic_assistant/data/repositories/talk_repository.dart';
import 'package:electronic_assistant/module/talk/controller.dart';
import 'package:electronic_assistant/resource/string.gen.dart';
import 'package:electronic_assistant/utils/error_handler.dart';
import 'package:electronic_assistant/utils/toast_util.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import '../../../data/bean/talk_original.dart';
import '../../../data/bean/talks.dart';
import '../../../data/repositories/account_repository.dart';
import '../../../widget/high_light_search_text.dart';

class OriginalController extends BaseController {
  final originalList = <TalkOriginal>[].obs;
  final String? talkId;

  StreamSubscription? _talkBeanListener;
  StreamSubscription? _talkStatusListener;
  StreamSubscription? _audioPlayingListener;
  StreamSubscription? _searchPrintListener;
  StreamSubscription? _searchOperationListener;

  final Map<int, int> searchTotalMap = {};

  OriginalController(this.talkId);

  TalkController get talkController => Get.find<TalkController>(tag: talkId);

  RxString get searchPrint => talkController.searchPrint;

  int searchNowIndex = 0;
  int searchTotalSize = 0;

  OriginalSearch? originalSearch;

  final ItemScrollController itemScrollController = ItemScrollController();

  @override
  void onReady() {
    super.onReady();
    _talkBeanListener = talkController.talkBean.listen((bean) {
      if (bean?.status.value == TalkStatus.analysisSuccess) {
        requestOriginal();
      }
    });
    _talkStatusListener =
        talkController.talkBean.value?.status.listen((status) {
      if (status == TalkStatus.analysisSuccess) {
        requestOriginal();
      }
    });

    _searchPrintListener = talkController.searchPrint.listen((txt) {
      if (talkController.checkTabBean.value?.type != TalkBarType.original) {
        return;
      }
      _dealOriginalSearch(txt);
    });

    _searchOperationListener =
        talkController.searchOperationCallback.listen((pair) {
      if (pair == null) {
        return;
      }
      if (pair.first != TalkBarType.original) {
        return;
      }
      if (searchTotalMap.isEmpty) {
        return;
      }
      if (pair.second == SearchOperationType.previous) {
        _dealSearchOperation(searchNowIndex - 1);
      } else if (pair.second == SearchOperationType.next) {
        _dealSearchOperation(searchNowIndex + 1);
      }
    });
    requestOriginal();
    setPlayAutoSelection();
  }

  void _dealSearchOperation(int updateIndex) {
    if (searchTotalMap.isEmpty) {
      originalSearch?.searchTargetBean?.checkIndex.value = null;
      originalSearch = null;
      searchNowIndex = 0;
      searchTotalSize = 0;
      talkController.updateSearchPositionDesc(searchNowIndex, searchTotalSize);
      return;
    }
    if (originalSearch == null) {
      _updateTargetBean(updateIndex, true);
    } else {
      updateSearchData(updateIndex);
    }

    scrollToIndex(originalSearch?.originalIndex);
    talkController.updateSearchPositionDesc(searchNowIndex, searchTotalSize);
  }

  void updateSearchData(int updateIndex) {
    if (updateIndex > searchNowIndex) {
      int nextIndex = (originalSearch?.searchTargetIndex ?? 0) + 1;
      if (nextIndex >= (originalSearch?.searchTargetLength ?? 0)) {
        //找下一个
        if (updateIndex > searchTotalSize) {
          updateIndex = 1;
        }
        _updateTargetBean(updateIndex, true);
      } else {
        originalSearch?.searchTargetIndex = nextIndex;
        originalSearch?.searchTargetBean?.checkIndex.value = nextIndex;
      }
    } else if (updateIndex < searchNowIndex) {
      //上一个
      int preIndex = (originalSearch?.searchTargetIndex ?? 0) - 1;
      if (preIndex < 0) {
        if (updateIndex <= 0) {
          updateIndex = searchTotalSize;
        }
        _updateTargetBean(updateIndex, false);
      } else {
        originalSearch?.searchTargetIndex = preIndex;
        originalSearch?.searchTargetBean?.checkIndex.value = preIndex;
      }
    }
    searchNowIndex = updateIndex;
  }

  void _updateTargetBean(int updateIndex, bool isNextTarget) {
    int count = 0;
    for (var entry in searchTotalMap.entries) {
      int key = entry.key;
      int value = entry.value;
      count += value;
      if (updateIndex <= count) {
        originalSearch ??= OriginalSearch();
        originalSearch?.searchTargetIndex = isNextTarget ? 0 : value - 1;
        originalSearch?.searchTargetLength = value;
        originalSearch?.originalIndex = key;
        originalSearch?.searchTargetBean?.checkIndex.value = null;
        originalSearch?.searchTargetBean = originalList[key];
        originalSearch?.searchTargetBean?.checkIndex.value =
            originalSearch?.searchTargetIndex;
        break;
      }
    }
    searchNowIndex = updateIndex;
  }

  _dealOriginalSearch(String txt) {
    searchTotalMap.clear();
    searchTotalSize = 0;
    for (int i = 0; i < originalList.length; i++) {
      TalkOriginal item = originalList[i];
      int count =
          HighlightSearchText.getHighlightTotal(item.sentence ?? '', txt);
      searchTotalSize += count;
      if (count > 0) {
        searchTotalMap.addAll({i: count});
      }
    }
    _dealSearchOperation(searchTotalMap.isNotEmpty ? 1 : 0);
  }

  void setPlayAutoSelection() {
    _audioPlayingListener = talkController.playingDuration.listen((duration) {
      if (duration == null) {
        return;
      }
      int time = duration.inMilliseconds;
      for (var item in originalList) {
        if (item.startMs == null || item.endMs == null) {
          continue;
        }
        if (item.startMs! <= time && item.endMs! >= time) {
          item.setSelected(true);
        } else {
          item.setSelected(false);
        }
      }
    });
  }

  void eventReport(String eventId, {Map<String, dynamic>? params}) {
    talkController.eventReport(eventId, params: params);
  }

  void requestOriginal() {
    if (talkController.talkBean.value?.status.value ==
        TalkStatus.analysisSuccess) {
      eventReport(EventId.event_101300);
    } else if (talkController.talkBean.value?.status.value ==
        TalkStatus.analysisFail) {
      eventReport(EventId.event_101301);
    }
    if (originalList.isNotEmpty) {
      return;
    }
    talkRepository
        .talkOriginal(talkController.talkBean.value?.id)
        .then((value) {
      originalList.value = value;
    });
  }

  void talkTranslateClick(TalkOriginal item) {
    if (!accountRepository.isLogin.value) {
      ToastUtil.showToast(StringName.errorCodeNoLogin.tr);
      return;
    }
    if (item.getTranslateStatus() == TalkTranslate.translating ||
        item.getTranslateStatus() == TalkTranslate.translated) {
      return;
    }
    if (item.sentence == null || item.sentence!.isEmpty) {
      ToastUtil.showToast('翻译内容为空');
      return;
    }
    item.setTranslateStatus(TalkTranslate.translating);
    talkRepository.talkTranslate(item.sentence!).then((result) {
      item.setTranslateStatus(TalkTranslate.translated);
      item.setTranslatedSentence(result.translation);
    }).catchError((error) {
      item.setTranslateStatus(TalkTranslate.normal);
      ErrorHandler.toastError(error);
    });
  }

  void scrollToIndex(int? index) {
    if (index == null) {
      return;
    }
    itemScrollController.scrollTo(
        index: index,
        duration: const Duration(milliseconds: 1),
        curve: Curves.easeInOut);
  }

  @override
  void onClose() {
    super.onClose();
    _talkBeanListener?.cancel();
    _talkStatusListener?.cancel();
    _audioPlayingListener?.cancel();
    _searchPrintListener?.cancel();
    _searchOperationListener?.cancel();
  }
}

class OriginalSearch {
  TalkOriginal? searchTargetBean;
  int? searchTargetIndex;
  int? searchTargetLength;
  int? originalIndex;
}
