// ignore_for_file: unnecessary_this

import 'dart:async';

import 'package:didvan/models/enums.dart';
import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/studio.dart';
import 'package:didvan/models/studio_details_data.dart';
import 'package:didvan/providers/core.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';

class StudioDetailsState extends CoreProvier {
  late StudioDetailsData studio;
  bool isStudioLoaded = false;
  StudioDetailsData? nextStudio;
  StudioDetailsData? prevStudio;
  late int initialIndex;
  StudioRequestArgs? args;
  StudioRequestArgs? podcastArgs;
  final List<int> relatedQueue = [];
  AppState alongSideState = AppState.idle;
  int _trackingTimerCounter = 0;
  Timer? _trackingTimer;

  StreamSubscription? _positionSubscription;

  int _selectedDetailsIndex = 0;
  Timer? timer;
  int timerValue = 10;
  bool stopOnPodcastEnds = false;

  int get selectedDetailsIndex => _selectedDetailsIndex;

  set selectedDetailsIndex(int value) {
    _selectedDetailsIndex = value;
    if (value == 2) {
      getRelatedContents();
    }
    notifyListeners();
  }

  Future<void> getStudioDetails(
    int id, {
    StudioRequestArgs? args,
    bool? isForward,
    bool fetchOnly = false,
  }) async {
    try {
      if (args != null) {
        this.args = args;
      }
      if (this.args?.type == 'podcast') {
        podcastArgs = this.args;
      }
      if (MediaService.currentPodcast?.id == id &&
          this.args?.type == 'podcast' &&
          !fetchOnly) {
        return;
      }
      _selectedDetailsIndex = 0;
      if (isForward != null) {
        if (isForward) {
          prevStudio = studio;
          studio = nextStudio!;
          nextStudio = null;
        } else {
          nextStudio = studio;
          studio = prevStudio!;
          prevStudio = null;
        }
        isStudioLoaded = true;
        notifyListeners();
        _handlePodcastPlayback(studio);
      }
      if (isForward == null) {
        if (this.args?.type == 'podcast') {
          MediaService.audioPlayerTag =
              'podcast-${MediaService.currentPodcast?.id ?? ''}';
        }
        appState = AppState.busy;
      } else {
        alongSideState = AppState.busy;
        notifyListeners();
      }
      final service = RequestService(
        RequestHelper.studioDetails(
          id,
          this.args ?? const StudioRequestArgs(page: 0),
        ),
      );
      await service.httpGet();
      nextStudio = null;
      prevStudio = null;
      if (stopOnPodcastEnds) {
        timerValue = 10;
      }
      stopOnPodcastEnds = false;
      if (service.isSuccess) {
        if (args?.type == 'video') {
          handleTracking(id: id, sendRequest: false);
        }
        final result = service.result;
        studio = StudioDetailsData.fromJson(result['studio']);
        isStudioLoaded = true;
        if (args?.page == 0) {
          initialIndex = 0;
          appState = AppState.idle;
          notifyListeners();
          return;
        }
        if (result['nextStudio'].isNotEmpty && this.args?.page != 0) {
          nextStudio = StudioDetailsData.fromJson(result['nextStudio']);
        }
        if (result['prevStudio'].isNotEmpty && this.args?.page != 0) {
          prevStudio = StudioDetailsData.fromJson(result['prevStudio']);
        }
        if (isForward == null && !fetchOnly) {
          await _handlePodcastPlayback(studio);
        }
        alongSideState = AppState.idle;
        appState = AppState.idle;
        notifyListeners();
        return;
      }
      if (isForward == null) {
        appState = AppState.failed;
      } else {
        alongSideState = AppState.failed;
        notifyListeners();
      }
    } catch (e) {
      update();
      appState = AppState.idle;
    }
  }

  Future<void> _handlePodcastPlayback(StudioDetailsData studio) async {
    _positionSubscription?.cancel();

    if (args?.type == 'podcast') {
      MediaService.currentPodcast = studio;
      MediaService.podcastPlaylistArgs = args;
      await MediaService.handleAudioPlayback(
        audioSource: studio.link,
        id: studio.id,
        isVoiceMessage: false,
        onTrackChanged: (isNext) {
          if (isNext && nextStudio != null) {
            getStudioDetails(nextStudio!.id);
          } else if (!isNext && prevStudio != null) {
            getStudioDetails(prevStudio!.id);
          }
        },
      );
      if (nextStudio != null) {
        _positionSubscription =
            MediaService.audioPlayer.positionStream.listen((event) {
          if (this.args?.type != 'podcast' ||
              MediaService.audioPlayerTag?.contains('message') == true) {
            return;
          }
          final duration =
              MediaService.duration ?? Duration(seconds: this.studio.duration);
          if (event.compareTo(duration) > 0 && this.nextStudio != null) {
            if (this.stopOnPodcastEnds) {
              MediaService.resetAudioPlayer();
              return;
            }
            this.getStudioDetails(this.nextStudio!.id, isForward: true);
          }
        });
      }
    } else {
      MediaService.audioPlayer.pause();
    }
  }

  Future<void> getRelatedContents() async {
    if (studio.relatedContents.isNotEmpty) return;
    relatedQueue.add(studio.id);
    final service = RequestService(RequestHelper.tag(
      ids: studio.tags.map((tag) => tag.id).toList(),
      itemId: studio.id,
      type: args?.type,
    ));
    await service.httpGet();
    if (service.isSuccess) {
      final relateds = service.result['contents'];
      for (var i = 0; i < relateds.length; i++) {
        studio.relatedContents.add(OverviewData.fromJson(relateds[i]));
      }
      if (relateds.isEmpty) {
        studio.relatedContentsIsEmpty = true;
      }
    } else {
      studio.relatedContentsIsEmpty = true;
    }
    notifyListeners();
  }

  void onCommentsChanged(int count) {
    studio.comments = count;
    notifyListeners();
  }

   Future<void> handleTracking({
    required int id,
    bool sendRequest = true,
  }) async {
    if (!sendRequest) {
      _trackingTimerCounter = 0;
      _trackingTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
        _trackingTimerCounter++;
        notifyListeners();
      });
      return;
    }
    final service = RequestService(
      RequestHelper.tracking(id, 'studio'),
      body: {
        'sec': _trackingTimerCounter,
      },
    );
    service.put();
    _trackingTimerCounter = 0;
    _trackingTimer?.cancel();
  }

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