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

import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:voice_buddies/app/api_repository/api_class.dart';
import 'package:voice_buddies/app/models/login_model.dart';

import '../../../models/common_model.dart';
import '../../../utils/all_imports.dart';

class UserDetailsController extends GetxController {
  LoginData? loginData;
  RxInt pageNo = 1.obs;
  RxBool isSignUp = true.obs;
  RxInt multipleLangSelectCount = 0.obs;
  RxBool isSelectedMoreThan = false.obs;
  RxBool isStarted = false.obs;
  RxBool isRecordingSaved = false.obs;
  RxBool isTickButton = false.obs;

  RxString userId = "".obs;
  RxString id = "".obs;
  RxString firstName = "".obs;
  RxString email = "".obs;
  RxString password = "".obs;
  RxString ccode = "".obs;
  RxString phone = "".obs;

  RxString selectedGender = "".obs;
  RxString selectedAge = "".obs;
  RxString selectedCurrentlyIAm = "".obs;
  RxString selectedCountry = "".obs;
  RxString selectedLanguage = "".obs;

  /// record
  String? path;
  Directory? appDirectory;
  bool isRecording = false;
  RecorderController? recorderController;
  PlayerController? playerController;
  File? file;
  Duration maxDuration = const Duration();
  Timer? timer;
  RxBool isTips = true.obs;

  List<CommonModel> gender = [
    CommonModel(name: AppStrings.male, isSelected: false),
    CommonModel(name: AppStrings.female, isSelected: false),
    CommonModel(name: AppStrings.other, isSelected: false),
    CommonModel(name: AppStrings.decline, isSelected: false),
  ];
  List<CommonModel> age = [
    CommonModel(name: AppStrings.lessThan, isSelected: false),
    CommonModel(name: AppStrings.twentyToTwentyNine, isSelected: false),
    // CommonModel(name: AppStrings.fiftyPlus, isSelected: false),
  ];
  List<CommonModel> currentlyIAm = [
    CommonModel(name: AppStrings.atSchool, isSelected: false),
    CommonModel(name: AppStrings.atCollege, isSelected: false),
    CommonModel(name: AppStrings.working, isSelected: false),
    CommonModel(name: AppStrings.inBetweenJobs, isSelected: false),
    CommonModel(name: AppStrings.decline, isSelected: false),
  ];
  List<CommonModel> whereILive = [
    CommonModel(name: AppStrings.northAmerica, isSelected: false),
    CommonModel(name: AppStrings.southAmerica, isSelected: false),
    CommonModel(name: AppStrings.europe, isSelected: false),
    CommonModel(name: AppStrings.africa, isSelected: false),
    CommonModel(name: AppStrings.asia, isSelected: false),
    CommonModel(name: AppStrings.australia, isSelected: false),
  ];
  List<CommonModel> spokenLanguage = [
    CommonModel(name: AppStrings.english, isSelected: false),
    CommonModel(name: AppStrings.spanish, isSelected: false),
    CommonModel(name: AppStrings.french, isSelected: false),
    CommonModel(name: AppStrings.german, isSelected: false),
    CommonModel(name: AppStrings.arabic, isSelected: false),
    CommonModel(name: AppStrings.russian, isSelected: false),
    CommonModel(name: AppStrings.portuguese, isSelected: false),
    CommonModel(name: AppStrings.mandarin, isSelected: false),
    CommonModel(name: AppStrings.cantonese, isSelected: false),
    CommonModel(name: AppStrings.korean, isSelected: false),
    CommonModel(name: AppStrings.hindi, isSelected: false),
    CommonModel(name: AppStrings.bengali, isSelected: false),
    CommonModel(name: AppStrings.urdu, isSelected: false),
    CommonModel(name: AppStrings.tamil, isSelected: false),
    CommonModel(name: AppStrings.telugu, isSelected: false),
    CommonModel(name: AppStrings.other, isSelected: false),
  ];
  String destinationPath = '';
  String destinationFileName = '';

  List<CommonModel> tipsList = [
    CommonModel(name: AppStrings.tipsFirst),
    CommonModel(name: AppStrings.tipsSecond),
    CommonModel(name: AppStrings.tipsThird),
    CommonModel(name: AppStrings.tipsFour),
    CommonModel(name: AppStrings.tipsFive),
  ];
  List<CommonModel> suggestionList = [
    CommonModel(image: AppImages.icGreenMike, name: AppStrings.pleaseTapThisGreenMikeIcon),
    CommonModel(image: AppImages.icYellowPlay, name: AppStrings.pleaseTapOrangePlayButton),
    CommonModel(image: AppImages.icDone, name: AppStrings.pleaseTapTickButton),
    CommonModel(image: AppImages.icNextArrow, name: AppStrings.pleaseTapToCompleteSignUp),
  ];

  @override
  Future<void> onInit() async {
    //  for download file store in this path //

    if (Get.arguments != null) {
      userId.value = Get.arguments[0].toString();
      pageNo.value = Get.arguments[1];
      isSignUp.value = Get.arguments[2];
      id.value = Get.arguments[3];
      firstName.value = Get.arguments[4];
      email.value = Get.arguments[5];
      password.value = Get.arguments[6];

      if (Get.arguments.length != 13) ccode.value = Get.arguments[7];
      if (Get.arguments.length != 13) phone.value = Get.arguments[8];

      if (Get.arguments.length == 13) {
        gender.indexWhere((element) {
          if (element.name == Get.arguments[7]) {
            element.isSelected = true;
            selectedGender.value = element.name;
            return true;
          }
          return false;
        });
        age.indexWhere((element) {
          if (element.name == Get.arguments[8]) {
            element.isSelected = true;
            selectedAge.value = element.name;
            return true;
          }
          return false;
        });
        currentlyIAm.indexWhere((element) {
          if (element.name == Get.arguments[9]) {
            element.isSelected = true;
            selectedCurrentlyIAm.value = element.name;
            return true;
          }
          return false;
        });

        whereILive.indexWhere((element) {
          if (element.name == Get.arguments[10]) {
            element.isSelected = true;
            selectedCountry.value = element.name;
            return true;
          }
          return false;
        });
        selectedLanguage.value = "";
        printAction("language select   Get.arguments[11]=-=-=-=-=-=-=-=-=-=-=-=->>${Get.arguments[11]}");
        for (var element in spokenLanguage) {
          Get.arguments[11].forEach((elements) {
            if (elements == element.name) {
              element.isSelected = true;
              selectedLanguage.value = selectedLanguage.value == "" ? element.name : "${selectedLanguage.value}, ${element.name}";
            }
          });
        }
        printAction("language select  selectedLanguage.value=-=-=-=-=-=-=-=-=-=-=-=->>${selectedLanguage.value}");
        path = Get.arguments[12];
      }
    }
    destinationPath = '/storage/emulated/0/download/ad';
    destinationFileName = '${DateTime.now().second}${DateTime.now().millisecond}.m4a';

    //  permission for storage //
    Map<Permission, PermissionStatus> statuses = await [
      Permission.storage,
    ].request();
    getUserData();
    getDir();
    initialiseControllers();
    playerController = PlayerController();
    playerStateSubscription = playerController!.onPlayerStateChanged.listen((_) {
      update();
    });
    super.onInit();
  }

  /// start and stop recording
  startOrStopRecording() async {
    if (isRecording) {
      // await recorderController!.pause();
      path = await recorderController!.stop(false);
      printAction("stop this record-----$path");
      isRecording = false;
      isStarted.value = true;
      printAction('finalPath is this is --------<<<<----->>>>>$path');
      stopTimer(resets: false);
      Fluttertoast.cancel();
      utils.showToast(message: AppStrings.recordingStop);
      update();
    } else {
      printAction('maxDuration in second--------<<<<----->>>>>${maxDuration.inSeconds}');
      // if (maxDuration.inSeconds < 20) {
      printAction("start recording");
      isRecording = true;
      isStarted.value = false;
      isTickButton.value = false;
      myWaveformData = [];
      printAction('recorderController.isRecording--------<<<<----->>>>>${recorderController!.isRecording}');
      recorderController!.stop(true);
      recorderController!.reset();
      maxDuration = const Duration(seconds: 0);
      startTimerCount();
      await recorderController!.record(
        path: path!,
        sampleRate: 24000,
        bitRate: 16000,
        androidEncoder: AndroidEncoder.aac,
      );
      utils.showToast(message: AppStrings.recordingStarted);
      update();
      printAction("path is isStarted -----------${pageNo.value}----$isStarted");
      // } else {
      //   Helper().showToast(message: 'You can only record 20 seconds at most', context: Get.context!);
      // }
    }
    update();
  }

  /// timer
  void startTimerCount() {
    printAction('timer started--------<<<<----->>>>>timer started');
    timer = Timer.periodic(const Duration(seconds: 1), (_) => addTime());
  }

  Future<void> addTime() async {
    const addSeconds = 1;
    final seconds = maxDuration.inSeconds + addSeconds;
    if (seconds < 0 || seconds >= 21) {
      utils.showToast(message: AppStrings.recordingStop);
      printAction('record max time is over');
      path = await recorderController!.stop(false);

      isRecording = false;
      isStarted.value = true;
      timer?.cancel();
      stopTimer(resets: false);
    } else {
      printAction('--------<<<<----->>>>>recording start is available');
      isRecording = true;
      isStarted.value = true;

      update();

      printAction('--------<<<<----->>>>>is time over done');
      maxDuration = Duration(seconds: seconds);
    }
    printAction(maxDuration.inSeconds.toString());
    update();
  }

  void stopTimer({bool resets = true}) {
    if (resets) {
      reset();
    }
    timer?.cancel();
    update();
  }

  void reset() {
    maxDuration = const Duration();
    stopTimer(resets: true);

    update();
  }

  RxString eventTimer = ''.obs;

  /// initialize recording controller
  initialiseControllers() {
    recorderController = RecorderController()
      ..androidEncoder = AndroidEncoder.aac
      ..androidOutputFormat = AndroidOutputFormat.mpeg4
      ..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
      ..sampleRate = 44100;
  }

  List<double> myWaveformData = [];
  late StreamSubscription<PlayerState> playerStateSubscription;

  /// Prepare audio player and play
  prepareAudioPlayer() async {
    Loading.show();
    await recorderController!.stop(false).then((value) {
      printAction('path is this--------<<<<----->>>>>$path');
    });
    myWaveformData = [];
    playerController = PlayerController();
    playerController?.onCurrentDurationChanged.listen((event) {
      eventTimer = (event ~/ 1000).toString().obs;
      printAction('event is this--------<<<<----->>>>>$eventTimer');
      update();
    });

    await playerController!.preparePlayer(path: path!, shouldExtractWaveform: true, volume: 1.0, noOfSamples: 100);
    await playerController!.extractWaveformData(path: path!, noOfSamples: 100).then((value) {
      isStarted.value = true;
      myWaveformData = value;
      Loading.dismiss();
      playPauseController();
      update();
    });

    printAction('maxDuration--------<<<<----->>>>>${playerController!.maxDuration}');
  }

  playPauseController() {
    printAction('controller.playerController!.playerState.isPlaying--------<<<<----->>>>>${playerController!.playerState.isPlaying}');
    if (!playerController!.playerState.isPlaying) {
      playerController!.startPlayer(finishMode: FinishMode.pause);
    } else {
      playerController!.pausePlayer();
    }
  }

  Future<void> copyAndRenameAudioFile(String sourcePath, String destinationPath, String destinationFileName) async {
    try {
      // Get the source file
      File sourceFile = File(sourcePath);

      // Read the contents of the source file
      List<int> contents = await sourceFile.readAsBytes();

      // Get the directory where you want to copy the file
      Directory destinationDir = Directory(destinationPath);

      // Check if the destination directory exists, if not create it
      if (!destinationDir.existsSync()) {
        destinationDir.createSync(recursive: true);
      }
      // Create a new File object with the destination path and write the contents to it
      File destinationFile = File('$destinationPath/$destinationFileName');
      await destinationFile.writeAsBytes(contents);

      printAction('File copied successfully to: ${destinationFile.path}');
    } catch (e) {
      printAction('Error copying file: $e');
    }
  }

//////////// ---------- API & Permission and get download path  //////////
//////////// ---------- API & Permission and get download path  //////////
//////////// ---------- API & Permission and get download path  //////////
//////////// ---------- API & Permission and get download path  //////////

  /// get user data from local storage
  getUserData() async {
    if (getStorageData.containKey(getStorageData.loginData)) {
      loginData = LoginData.fromJson(getStorageData.readObject(getStorageData.loginData));
    }
  }

  /// create audio path
  getDir() async {
    path = "${await getDownloadFolderPath()}/voiceBuddiesRecording.m4a";

    printAction('download path ---------------->> $path');
    checkPermission();
    update();
  }

  /// download recorder path get
  Future<String> getDownloadFolderPath() async {
    Directory? downloadsDirectory = Platform.isAndroid ? await getDownloadsDirectory() : await getApplicationDocumentsDirectory();
    String downloadFolderPath = downloadsDirectory!.path;
    return downloadFolderPath;
  }

  /// Request microphone permission
  checkPermission() async {
    final status = await Permission.microphone.request();
    printAction(status.toString());
    if (status.isGranted) {
      printAction("isGranted");
    } else if (status.isPermanentlyDenied) {
      await openAppSettings();
      Get.back();
      printAction("isPermanentlyDenied");
    } else if (status.isDenied) {
      await openAppSettings();
      Get.back();
    }
    update();
  }

  /// Send OTP Api
  sendOTP() async {
    FormData formData = FormData.fromMap({
      "email": email,
      HttpUtil.ccode: ccode.value,
      HttpUtil.phone: phone.value,
    });

    final data = await APIFunction().apiCall(
      apiName: Constants.sendOtp,
      params: formData,
    );

    LoginDataModel model = LoginDataModel.fromJson(data);

    if (model.responseCode == 1) {
      await copyAndRenameAudioFile(path!, destinationPath, destinationFileName);
      recorderController?.stop(false);
      playerController?.stopAllPlayers();
      Get.toNamed(
        Routes.OTP,
        arguments: [
          isSignUp.value, //0
          id.value, //1
          firstName.value, //2
          email.value, //3
          password.value, //4
          selectedGender.value, //5
          selectedAge.value, //6
          selectedCurrentlyIAm.value, //7
          selectedCountry.value, //8
          selectedLanguage.value, //9
          path, //10
          ccode.value, //11
          phone.value, //12
        ],
      );
      utils.showSnackBar(message: 'Your voice recording has been successfully saved.', statusCode: 1);
    } else {
      utils.showSnackBar(message: model.responseMsg!, statusCode: model.responseCode);
    }
  }

  @override
  void onClose() {
    playerController?.stopAllPlayers();
    playerController?.dispose();
    recorderController!.dispose();
    if (!isClosed) {
      timer?.cancel();
      recorderController!.stop(false);
      playerController?.dispose();
    }
    super.onClose();
  }
}

///data/user/0/com.voicebuddies.app/app_flutter/voiceBuddiesRecording.m4a
///data/data/com.voicebuddies.app/app_flutter/voiceBuddiesRecording.m4a
