import 'dart:async';
import 'dart:math';

import 'package:didvan/models/enums.dart';
import 'package:didvan/models/news_details_data.dart';
import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';

class NewsDetailsState extends CoreProvier {
  final List<NewsDetailsData?> news = [];
  late final int initialIndex;
  late final NewsRequestArgs args;
  late Timer _trackingTimer;
  int _trackingTimerCounter = 0;
  bool isFetchingNewItem = false;
  final List<int> relatedQueue = [];

  int _currentIndex = 0;
  int get currentIndex => _currentIndex;

  NewsDetailsData get currentNews => news[_currentIndex]!;

  Future<void> getNewsDetails(int id, {bool? isForward}) async {
    if (isForward == null) {
      appState = AppState.busy;
    } else {
      isFetchingNewItem = true;
      notifyListeners();
    }
    final service = RequestService(RequestHelper.newsDetails(id, args));
    await service.httpGet();
    _handleTracking(sendRequest: isForward != null);
    if (service.isSuccess) {
      final result = service.result;
      final newsItem = NewsDetailsData.fromJson(result['news']);
      if (args.page == 0) {
        news.add(newsItem);
        initialIndex = 0;
        appState = AppState.idle;
        return;
      }
      NewsDetailsData? prevNews;
      if (result['prevNews'].isNotEmpty) {
        prevNews = NewsDetailsData.fromJson(result['prevNews']);
      }
      NewsDetailsData? nextNews;
      if (result['nextNews'].isNotEmpty) {
        nextNews = NewsDetailsData.fromJson(result['nextNews']);
      }
      if (isForward == null) {
        news.addAll(List.generate(max(newsItem.order - 2, 0), (index) => null));
        if (prevNews != null) {
          news.add(prevNews);
        }
        news.add(newsItem);
        if (nextNews != null) {
          news.add(nextNews);
        }
        _currentIndex = initialIndex = newsItem.order - 1;
      } else if (isForward) {
        if (!exists(nextNews) && nextNews != null) {
          news.add(nextNews);
        }
        _currentIndex++;
      } else if (!isForward) {
        if (!exists(prevNews) && prevNews != null) {
          news[_currentIndex - 2] = prevNews;
        }
        _currentIndex--;
      }
      isFetchingNewItem = false;
      appState = AppState.idle;
      return;
    }
    if (isForward == null) {
      appState = AppState.failed;
    }
  }

  bool exists(NewsDetailsData? newsItem) =>
      news.any((n) => newsItem != null && n != null && n.id == newsItem.id);

  void onCommentsChanged(int count) {
    news.firstWhere((item) => item?.id == currentNews.id)!.comments = count;
    notifyListeners();
  }

  Future<void> _handleTracking({bool sendRequest = true}) async {
    if (!sendRequest) {
      _trackingTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
        _trackingTimerCounter++;
      });
      return;
    }
    //send request
    _trackingTimerCounter = 0;
  }

  Future<void> getRelatedContents() async {
    if (currentNews.relatedContents.isNotEmpty) return;
    relatedQueue.add(currentNews.id);
    final service = RequestService(RequestHelper.tag(
      ids: currentNews.tags.map((tag) => tag.id).toList(),
      itemId: currentNews.id,
      type: 'news',
    ));
    await service.httpGet();
    if (service.isSuccess) {
      final relateds = service.result['contents'];
      for (var i = 0; i < relateds.length; i++) {
        news
            .where((element) => element != null)
            .firstWhere((element) => element!.id == currentNews.id)!
            .relatedContents
            .add(OverviewData.fromJson(relateds[i]));
      }
      notifyListeners();
    }
  }

  @override
  void dispose() {
    _trackingTimer.cancel();
    super.dispose();
  }
}
