import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/api/music_api.dart';
import 'package:tone_snap/data/enum/music_type.dart';
import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/search_result_model.dart';
import 'package:tone_snap/data/models/search_result_tabbar_model.dart';
import 'package:tone_snap/data/models/search_suggestions_model.dart';
import 'package:tone_snap/data/storage/music_box.dart';
import 'package:tone_snap/modules/sideb/search_music/search_music_controller.dart';
import 'package:tone_snap/modules/sideb/search_result_child/search_result_child_controller.dart';
import 'package:tone_snap/modules/sideb/search_result_child/search_result_child_view.dart';
import 'package:tone_snap/modules/sideb/search_result_child_optimum/search_result_child_optimum_controller.dart';
import 'package:tone_snap/modules/sideb/search_result_child_optimum/search_result_child_optimum_view.dart';
import 'package:tone_snap/utils/obj_util.dart';

class SearchResultController extends GetxController with GetTickerProviderStateMixin {
  static SearchResultController get to => Get.find<SearchResultController>();
  var textEditingController = TextEditingController();
  final FocusNode myFocusNode = FocusNode();
  var shouldAutofocus = true;
  var searchKeyword = ''.obs;
  var cancelToken = CancelToken();
  var searchSuggestionsList = <String>[].obs;
  var searchSuggestionsViewState = ViewState.normal.obs;

  var tabController = Rx<TabController?>(null);
  var tabs = <SearchResultTabBarModel>[];
  var pages = <Widget>[];
  var searchResultViewState = Rx<ViewState?>(null);

  @override
  void onReady() {
    super.onReady();
    searchKeyword.value = Get.arguments ?? '';
    if (ObjUtil.isNotEmpty(searchKeyword.value)) {
      shouldAutofocus = false;
      textEditingController.text = searchKeyword.value;
      onTapSearch(searchKeyword.value);
    }
    if (shouldAutofocus) {
      myFocusNode.requestFocus();
    }
  }

  @override
  void onClose() {
    myFocusNode.dispose();
    textEditingController.dispose();
    if (tabController.value != null) tabController.value?.dispose();
    super.onClose();
  }

  void onTapCancel() {
    Get.back();
  }

  Future<void> onChanged(String value) async {
    searchKeyword.value = value;
    searchSuggestionsList.clear();
    cancelToken.cancel();
    _cleanTab();
    if (ObjUtil.isEmpty(value)) {
      return;
    }
    searchSuggestionsViewState.value = ViewState.loading;
    cancelToken = CancelToken();
    SearchSuggestionsModel? searchSuggestionsModel = await MusicApi.searchSuggestions(input: value, cancelToken: cancelToken);
    if (searchSuggestionsModel != null) {
      var contents1 = searchSuggestionsModel.contents;
      if (contents1 != null && contents1.isNotEmpty) {
        var contents2 = contents1[0].searchSuggestionsSectionRenderer?.contents;
        if (contents2 != null && contents2.isNotEmpty) {
          for (var o in contents2) {
            var query = o.searchSuggestionRenderer?.navigationEndpoint?.searchEndpoint?.query;
            if (ObjUtil.isNotEmpty(query)) {
              searchSuggestionsList.add(query!);
            }
          }
        }
      }
    }
    searchSuggestionsViewState.value = ViewState.normal;
  }

  void cleanTextEditingController() {
    searchKeyword.value = '';
    textEditingController.clear();
    searchSuggestionsList.clear();
    cancelToken.cancel();
    _cleanTab();
  }

  Future<void> _cleanTab() async {
    searchResultViewState.value = null;
    if (tabController.value != null) tabController.value?.dispose();
    tabController.value = null;
    if (Get.isRegistered<SearchResultChildOptimumController>()) {
      await Get.delete<SearchResultChildOptimumController>();
    }
    for (var o in tabs) {
      var tag = '${o.title}-${o.params}';
      if (Get.isRegistered<SearchResultChildController>(tag: tag)) {
        await Get.delete<SearchResultChildController>(tag: tag);
      }
    }
    tabs.clear();
    pages.clear();
  }

  Future<void> onTapSearch(String value, {bool isSearchSuggestionsItem = true}) async {
    if (ObjUtil.isEmpty(textEditingController.text)) {
      return;
    }
    if (isSearchSuggestionsItem) {
      textEditingController.text = value;
    }
    await MusicBox().putSearchHistory(textEditingController.text);
    if (Get.isRegistered<SearchMusicController>()) {
      SearchMusicController.to.getList();
    }
    await _cleanTab();
    searchResultViewState.value = ViewState.loading;
    await _searchPreviewResult(value);
    searchResultViewState.value = tabs.isNotEmpty ? ViewState.normal : ViewState.empty;
    tabController.value = TabController(length: tabs.length, vsync: this);
  }

  Future<void> _searchPreviewResult(String keyword) async {
    Map<String, dynamic> queryParameters = {
      'prettyPrint': false,
      'query': keyword
    };
    SearchResultModel? searchResultModel = await MusicApi.search<SearchResultModel>(queryParameters: queryParameters, formJson: SearchResultModel.fromMap);
    if (searchResultModel != null) {
      var tabs = searchResultModel.contents?.tabbedSearchResultsRenderer?.tabs;
      if (tabs != null && tabs.isNotEmpty) {
        var contents1 = tabs[0].tabRenderer?.content?.sectionListRenderer?.contents;
        if (contents1 != null && contents1.isNotEmpty) {
          for (var o in contents1) {
            var searchResultTabBarModel = SearchResultTabBarModel();
            MusicModel? musicModelCard;
            if (o.musicCardShelfRenderer != null) {
              musicModelCard = MusicModel();
              var runs1 = o.musicCardShelfRenderer?.header?.musicCardShelfHeaderBasicRenderer?.title?.runs;
              if (runs1 != null && runs1.isNotEmpty) {
                searchResultTabBarModel.title = runs1[0].text;
                searchResultTabBarModel.uniqueId = runs1[0].text;
              }
              var thumbnails = o.musicCardShelfRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails;
              if (thumbnails != null && thumbnails.isNotEmpty) {
                musicModelCard.coverUrl = thumbnails.last.url;
              }
              var runs2 = o.musicCardShelfRenderer?.title?.runs;
              if (runs2 != null && runs2.isNotEmpty) {
                musicModelCard.title = runs2[0].text;
                if (runs2[0].navigationEndpoint?.watchEndpoint != null) {
                  musicModelCard.musicType = runs2[0].navigationEndpoint?.watchEndpoint?.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType;
                } else if (runs2[0].navigationEndpoint?.browseEndpoint != null) {
                  musicModelCard.browseId = runs2[0].navigationEndpoint?.browseEndpoint?.browseId;
                  musicModelCard.musicType = runs2[0].navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType;
                }
              }
              var runs3 = o.musicCardShelfRenderer?.subtitle?.runs;
              if (runs3 != null && runs3.isNotEmpty) {
                musicModelCard.subtitle = runs3.map((e) => e.text).join();
              }
              var items = o.musicCardShelfRenderer?.menu?.menuRenderer?.items;
              if (items != null && items.isNotEmpty) {
                musicModelCard.playlistId = items[0].menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId;
              }
              searchResultTabBarModel.musicList ??= <MusicModel>[];
              this.tabs.add(searchResultTabBarModel);
            } else if (o.musicShelfRenderer != null) {
              var runs = o.musicShelfRenderer?.title?.runs;
              if (runs != null && runs.isNotEmpty) {
                searchResultTabBarModel.title = runs[0].text;
              }
              var contents2 = o.musicShelfRenderer?.contents;
              if (contents2 != null && contents2.isNotEmpty) {
                for (var e in contents2) {
                  var musicModel = MusicModel();
                  var thumbnails = e.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails;
                  if (thumbnails != null && thumbnails.isNotEmpty) {
                    musicModel.coverUrl = thumbnails.last.url;
                  }
                  var flexColumns = e.musicResponsiveListItemRenderer?.flexColumns;
                  if (flexColumns != null && flexColumns.isNotEmpty) {
                    for (var i = 0; i < flexColumns.length; ++i) {
                      var m = flexColumns[i];
                      var runs = m.musicResponsiveListItemFlexColumnRenderer?.text?.runs;
                      if (runs != null && runs.isNotEmpty) {
                        if (i == 0) {
                          musicModel.title = runs[0].text;
                          musicModel.videoId = runs[0].navigationEndpoint?.watchEndpoint?.videoId;
                          musicModel.musicType = runs[0].navigationEndpoint?.watchEndpoint?.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType;
                        } else {
                          musicModel.subtitle = ObjUtil.getStr(musicModel.subtitle) + runs.map((e) => e.text).join();
                        }
                      }
                    }
                  }
                  var items = e.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items;
                  if (items != null && items.isNotEmpty) {
                    musicModel.playlistId = items[0].menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId;
                  }
                  if (e.musicResponsiveListItemRenderer?.navigationEndpoint != null) {
                    musicModel.browseId = e.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId;
                    musicModel.musicType = e.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType;
                  }
                  searchResultTabBarModel.musicList ??= <MusicModel>[];
                  if (musicModelCard != null && musicModel.musicType == musicModelCard.musicType) {
                    searchResultTabBarModel.musicList!.add(musicModelCard.copyWith());
                    musicModelCard = null;
                  }
                  if (musicModel.musicType == MusicType.musicVideoTypeAtv.name
                      || musicModel.musicType == MusicType.musicPageTypeAlbum.name
                      || musicModel.musicType == MusicType.musicPageTypePlaylist.name) {
                    searchResultTabBarModel.musicList!.add(musicModel);
                  }
                }
              }
              bool isAdd = false;
              searchResultTabBarModel.musicList?.map((e) => isAdd = e.musicType == MusicType.musicVideoTypeAtv.name
                  || e.musicType == MusicType.musicPageTypeAlbum.name
                  || e.musicType == MusicType.musicPageTypePlaylist.name).toList();
              if (isAdd) {
                this.tabs.add(searchResultTabBarModel);
              }
            }
          }
        }

        var chips = tabs[0].tabRenderer?.content?.sectionListRenderer?.header?.chipCloudRenderer?.chips;
        if (chips != null && chips.isNotEmpty) {
          for (var o in chips) {
            var searchResultTabBarModel = SearchResultTabBarModel();
            var runs = o.chipCloudChipRenderer?.text?.runs;
            if (runs != null && runs.isNotEmpty) {
              searchResultTabBarModel.title = runs[0].text;
            }
            searchResultTabBarModel.params = o.chipCloudChipRenderer?.navigationEndpoint?.searchEndpoint?.params;
            searchResultTabBarModel.uniqueId = o.chipCloudChipRenderer?.uniqueId;

            for (var e in this.tabs) {
              if (e.title == searchResultTabBarModel.title) {
                e.uniqueId = searchResultTabBarModel.uniqueId;
                e.params = searchResultTabBarModel.params;
                if (e.musicList != null) {
                  for (var o in e.musicList!) {
                    o.params = searchResultTabBarModel.params;
                  }
                }
                break;
              }
            }
          }
          for (var i = 0; i < this.tabs.length; ++i) {
            if (i == 0) {
              pages.add(const SearchResultChildOptimumView());
            } else {
              pages.add(SearchResultChildView(searchResultTabBarModel: this.tabs[i]));
            }
          }
        }
      }
    }
  }
}
