import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:html';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_image_slideshow/flutter_image_slideshow.dart';
import 'package:intl/intl.dart';
import 'package:queuedisplay/model/branch_model.dart';
import 'package:queuedisplay/model/display_counter_dedicated_modelv2.dart';
import 'package:queuedisplay/model/service_model.dart';
import 'package:queuedisplay/provider/all_service_provider.dart';
import 'package:queuedisplay/screen/with_media_promo.dart';
import 'package:queuedisplay/widget/my_counter_customer_service_dedicated.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:flutter/material.dart';
import 'package:text_scroll/text_scroll.dart';

import '../app/constant.dart';
import '../app/route.dart';
import '../model/layanan_dokter.dart';
import '../provider/display_counter_dedicated_provider.dart';
import '../widget/clock.dart';
import '../widget/my_antrian_customer_service_dedicated.dart';
import '../widget/my_error_dialog.dart';
import 'no_media_promo.dart';

class CustomerServiceDedicatedV2 extends StatefulHookConsumerWidget {
  const CustomerServiceDedicatedV2({super.key});

  @override
  ConsumerState<ConsumerStatefulWidget> createState() =>
      _CustomerServiceDedicatedV2State();
}

class _CustomerServiceDedicatedV2State
    extends ConsumerState<CustomerServiceDedicatedV2> {
  late IO.Socket socket;
  late String typeJson = "";

  @override
  void initState() {
    initSocket();
    super.initState();
  }

  initSocket() {
    socket = IO.io('https://${Constant.baseSocket}:9099', <String, dynamic>{
      'autoConnect': false,
      'transports': ['websocket'],
    });

    socket.connect();
    socket.onConnect((_) {
      print('Connection established');
    });
    socket.onDisconnect((_) => print('Connection Disconnection'));
    socket.onConnectError((err) => print(err));
    socket.onError((err) => print(err));
  }

  @override
  void dispose() {
    socket.disconnect();
    socket.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final isLoading = useState(false);

    final errorMessage = useState("");
    final ListErrorMessage = useState<List<String>>(List.empty());
    final listService =
        useState<List<DisplayCounterDedicatedModelV2>>(List.empty());

    final listBelumDilayani = useState<List<NotServed>>(List.empty());
    final listSedangDilayani = useState<List<Served>>(List.empty());
    final listCall = useState<List<Call>>(List.empty());
    final selectedBranch = useState(BranchModel(mBranchID: '0'));

    final judul = useState("");
    final dataLayanan = useState<List<int>>(List.empty());
    final lastTimeCall =
        useState<DateTime>(DateTime.now().subtract(Duration(minutes: 1)));

    final locationIDCall = useState(0);
    final serviceIDArr = useState<List>(List.empty());
    final serviceIDArrSuara = useState<List>(List.empty());
    final selectedCounter = useState<List<Layanan>>(List.empty());
    final scrlCnt = useScrollController();

    final activeSoundDoctor = useState<List<int>>(List.empty());
    final activeSoundCounter = useState<List<int>>(List.empty());
    final activeSoundSamplingLocation = useState<List<int>>(List.empty());
    final listNotification = useState<List<String>>(List.empty());
    final serviceIDCounterArr = useState<List<int>>(List.empty());
    final notifState = useState<Map<String, DateTime>>({});

    // media promo
    final tanpaMediaPromo = useState(false);

    void goFullScreen() {
      document.documentElement?.requestFullscreen();
    }

    // mp3
    wordToMp3(int number) {
      var result = "";
      print("number = $number");
      int ribu = (number / 1000).floor();
      // print("ribu = $ribu");
      if (ribu > 0) {
        if (ribu == 1) {
          result += "seribu" + '${number % 1000 == 0 ? "" : ","}';
        } else {
          result += "$ribu,ribu" + '${number % 1000 == 0 ? "" : ","}';
        }
      }

      int cur = number - ribu * 1000;
      int ratus = (cur / 100).floor();
      // print("ratus = $ratus");
      if (ratus > 0) {
        if (ratus == 1) {
          result += "100";
        } else {
          result += "$ratus,ratus";
        }
      }

      cur = cur - ratus * 100;
      int puluh = (cur / 10).floor();
      // print("puluh = $puluh");
      if (puluh > 0) {
        if (result != "") result += ",";

        if (puluh == 1) {
          if (cur - 10 == 1) {
            result += "11";
            return result;
          }
//         else if(cur - 10 == 0){
//           result += "10";
//           return result;
//         }
          else {
            int hasil = cur - 10;
            if (hasil == 0) {
              result += "10";
            } else {
              result += "$hasil,belas";
            }
          }
        } else {
          result += "$puluh,puluh";
        }
      }

      cur = cur - (puluh * 10);
      // print("akhir = $cur");
      if (cur > 0) {
        if (puluh == 1) {
          result += "";
        } else {
          if (result != "") result += ",";
          result += "$cur";
        }
      }

      return result;
    }

    void downloadMp3(String param) async {
      try {
        var url = "http://${Constant.baseSocket}/audio/?prm=$param";
        final player = AudioPlayer();
        player.setSource(UrlSource(url));
        print(url);
        player.resume();
      } catch (e) {
        print(e);
      }
    }

    process_sound(String number, String Counter) {
      String antrian = number.replaceAll(RegExp(r'[^0-9]'), '');
      String code = number.replaceAll(RegExp(r'[^A-Z]'), '');
      var splitedCode = code.split("");
      String joinCode = splitedCode.join(",");

      String counterNum = Counter.replaceAll(RegExp(r'[^0-9]'), '');
      String counterCode = Counter.replaceAll(RegExp(r'[^A-Z]'), '');
      var splitedCodeCounter = counterCode.split("");
      String joinCodeCounter = splitedCodeCounter.join(",");

      if (antrian.isNotEmpty && counterNum.isNotEmpty) {
        String param = "antrian,$joinCode," +
            "${wordToMp3(int.parse(antrian))}," +
            "counter,$joinCodeCounter," +
            wordToMp3(int.parse(counterNum));
        downloadMp3(param);
      }
    }

    process_sound_sampling(String number, String Counter) {
      try {
        String antrian = number.replaceAll(RegExp(r'[^0-9]'), '');
        String code = number.replaceAll(RegExp(r'[^A-Z]'), '');
        var splitedCode = code.split("");
        String joinCode = splitedCode.join(",");

        String counterNum = Counter.replaceAll(RegExp(r'[^0-9]'), '');
        String counterCode = Counter.replaceAll(RegExp(r'[^A-Z]'), '');
        var splitedCodeCounter = counterCode.split("");
        String joinCodeCounter = splitedCodeCounter.join(",");

        String param = "antrian,$joinCode," +
            "${wordToMp3(int.parse(antrian))},ruangan,r$Counter";
        print(param);
        downloadMp3(param);
        // }
      } catch (e) {
        print(e);
      }
    }

    process_sound_doctor(String number, String Counter, String serviceID) {
      try {
        String antrian = number.replaceAll(RegExp(r'[^0-9]'), '');
        String code = number.replaceAll(RegExp(r'[^A-Z]'), '');
        var splitedCode = code.split("");
        String joinCode = splitedCode.join(",");
        var allLayanan = ref.read(allServiceDoctorProvider.notifier).state;
        LayananDokter lyn = allLayanan.firstWhere(
            (element) => element.id == int.parse(serviceID.toString()));

        if (antrian.isNotEmpty && lyn.doctorName != '') {
          String service = lyn.doctorName;
          String processService = service
              .replaceAll('.', '')
              .replaceAll(' ', '_')
              .replaceAll(',', '')
              .toLowerCase();
          String param = "antrian,$joinCode," +
              "${wordToMp3(int.parse(antrian))}," +
              processService;
          downloadMp3(param);
        }
      } catch (e) {
        print(e);
      }
    }

    // mp3
    // socket.off("notification", (data) {});
    socket.on('notification', (data) {
      String pesan = data['type'];
      if (notifState.value.containsKey(pesan)) {
        var lasDate = notifState.value[pesan];
        if (DateTime.now()
            .subtract(const Duration(seconds: 10))
            .isBefore(lasDate!)) {
          return;
        }
        var notifNew = notifState.value;
        notifNew[pesan] = DateTime.now();
        notifState.value = notifNew;
      } else {
        var notifNew = notifState.value;
        notifNew[pesan] = DateTime.now();
        notifState.value = notifNew;
      }
      print(data);
      // typeJsonSocketIO.value = data['type'];
      var splited_pesan = pesan.split(".");
      // var splited_pesan = pesan.split(".");
      // print(splited_pesan);
      if (splited_pesan[0] == 'call') {
        var xList = listNotification.value.toList();
        List<String> msgList = xList;
        if (splited_pesan[1] == 'fo') {
          var serviceValidation = serviceIDArr.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[2].toString()));

          var counterValidation = dataLayanan.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[5].toString()));
          locationIDCall.value = int.parse(splited_pesan[2]);

          if (serviceValidation.isNotEmpty && counterValidation.isNotEmpty) {
            ref.read(displayProvider.notifier).listDisplayByCounterID(
                dataLayanan.value, selectedBranch.value.mBranchID ?? "0");
          }
        }
        if (xList.isEmpty) {
          // if (activeSoundDoctor.value.isNotEmpty && splited_pesan[1] == 'kd') {
          //   var validation =
          //       activeSoundDoctor.value.contains(int.parse(splited_pesan[2]));
          //   if (validation) {
          //     msgList.add(pesan);
          //   }
          // }
          if (activeSoundCounter.value.isNotEmpty &&
              splited_pesan[1] == 'fo' &&
              splited_pesan[6] == selectedBranch.value.mBranchID) {
            var serviceValidation = serviceIDArrSuara.value.where((element) =>
                int.parse(element.toString()) ==
                int.parse(splited_pesan[2].toString()));

            var counterValidation = activeSoundCounter.value.where((element) =>
                int.parse(element.toString()) ==
                int.parse(splited_pesan[5].toString()));
            locationIDCall.value = int.parse(splited_pesan[2]);
            if (serviceValidation.isNotEmpty && counterValidation.isNotEmpty) {
              msgList.add(pesan);
            }
          }
          // if (activeSoundSamplingLocation.value.isNotEmpty &&
          //     splited_pesan[1] == 'sm') {
          //   var validation = activeSoundSamplingLocation.value
          //       .contains(int.parse(splited_pesan[2]));
          //   if (validation) {
          //     msgList.add(pesan);
          //   }
          // }
        }
        // else {
        //   if (activeSoundDoctor.value.isNotEmpty && splited_pesan[1] == 'kd') {
        //     var validation =
        //         activeSoundDoctor.value.contains(int.parse(splited_pesan[2]));
        //     var msgValidation = msgList.contains(pesan.toString());
        //     if (validation && !msgValidation) {
        //       msgList.add(pesan);
        //     }
        //   }
        //   if (activeSoundCounter.value.isNotEmpty && splited_pesan[1] == 'fo') {
        //     var validation =
        //         activeSoundCounter.value.contains(int.parse(splited_pesan[5]));
        //     var counterValidation =
        //         serviceIDCounterArr.value.contains(int.parse(splited_pesan[2]));
        //     var msgValidation = msgList.contains(pesan.toString());
        //     if (validation && !msgValidation && counterValidation) {
        //       msgList.add(pesan);
        //     }
        //   }
        //   if (activeSoundSamplingLocation.value.isNotEmpty &&
        //       splited_pesan[1] == 'sm') {
        //     var validation = activeSoundSamplingLocation.value
        //         .contains(int.parse(splited_pesan[2]));
        //     var msgValidation = msgList.contains(pesan.toString());
        //     if (validation && !msgValidation) {
        //       msgList.add(pesan);
        //     }
        //   }
        // }
        listNotification.value = msgList;
        print('List Notification : ${listNotification.value}');
      } else if (splited_pesan[0] == 'skip') {
        if (splited_pesan[1] == 'fo' &&
            splited_pesan[4] == selectedBranch.value.mBranchID) {
          var serviceValidation = serviceIDArr.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[2].toString()));
          var counterValidation = dataLayanan.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[3].toString()));
          if (serviceValidation.isNotEmpty && counterValidation.isNotEmpty) {
            ref.read(displayProvider.notifier).listDisplayByCounterID(
                dataLayanan.value, selectedBranch.value.mBranchID ?? "0");
          }
        }
      } else if (splited_pesan[0] == 'serve') {
        if (splited_pesan[1] == 'fo' &&
            splited_pesan[4] == selectedBranch.value.mBranchID) {
          var serviceValidation = serviceIDArr.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[2].toString()));
          var counterValidation = dataLayanan.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[3].toString()));

          if (serviceValidation.isNotEmpty && counterValidation.isNotEmpty) {
            ref.read(displayProvider.notifier).listDisplayByCounterID(
                dataLayanan.value, selectedBranch.value.mBranchID ?? "0");
          }
        }
      } else if (splited_pesan[0] == 'done') {
        if (splited_pesan[1] == 'fo' &&
            splited_pesan[4] == selectedBranch.value.mBranchID) {
          var serviceValidation = serviceIDArr.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[2].toString()));
          var counterValidation = dataLayanan.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[3].toString()));

          if (serviceValidation.isNotEmpty && counterValidation.isNotEmpty) {
            ref.read(displayProvider.notifier).listDisplayByCounterID(
                dataLayanan.value, selectedBranch.value.mBranchID ?? "0");
          }
        }
      } else if (splited_pesan[0] == "printed") {
        if (splited_pesan[1] == 'fo') {
          var serviceValidation = serviceIDArr.value.where((element) =>
              int.parse(element.toString()) ==
              int.parse(splited_pesan[2].toString()));
          if (serviceValidation.isNotEmpty &&
              splited_pesan[3] == selectedBranch.value.mBranchID) {
            ref.read(displayProvider.notifier).listDisplayByCounterID(
                dataLayanan.value, selectedBranch.value.mBranchID ?? "0");
          }
        }
      }
    });

    void autoScroll() {
      if (scrlCnt.hasClients) {
        if (scrlCnt.offset == 0) {
          scrlCnt.animateTo(scrlCnt.position.maxScrollExtent,
              duration: Duration(milliseconds: 100), curve: Curves.linear);
        } else {
          scrlCnt.animateTo(scrlCnt.position.minScrollExtent,
              duration: Duration(milliseconds: 100), curve: Curves.linear);
        }
      }
    }

    Timer? tmr2;
    Timer? tmr;
    useEffect(() {
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
        goFullScreen();

        tmr = Timer.periodic(Duration(seconds: 5), (timer) {
          autoScroll();
        });

        final prefs = await SharedPreferences.getInstance();
        var rawData = prefs.getString('counter_dedicated') ?? 'a';

        if (rawData != 'a') {
          print(rawData);
          var data = json.decode(rawData);
          judul.value = data['judul'];

          serviceIDArr.value = data['serviceID'];

          // suara
          serviceIDArrSuara.value = data['serviceIDSuara'];

          // klu di check(true) maka tanpa media promo
          tanpaMediaPromo.value = data['tanpaMediaPromo'];
          //Selected branch
          selectedBranch.value = BranchModel.fromJson(data['selectedBranch']);

          List<int> listServiceID = List.empty(growable: true);
          for (var x in data['activeLayanan']) {
            listServiceID.add(int.parse(x.toString()));
          }
          dataLayanan.value = listServiceID;

          List<int> listSoundDoctorID = List.empty(growable: true);
          for (var x in data['activeSoundDoctor']) {
            listSoundDoctorID.add(int.parse(x.toString()));
          }
          activeSoundDoctor.value = listSoundDoctorID;

          List<int> listSoundSamplingID = List.empty(growable: true);
          for (var x in data['activeSoundSamplingLocation']) {
            listSoundSamplingID.add(int.parse(x.toString()));
          }
          activeSoundSamplingLocation.value = listSoundSamplingID;

          List<int> listsoundCounter = List.empty(growable: true);
          for (var x in data['activeSoundCounter']) {
            listsoundCounter.add(int.parse(x.toString()));
          }
          activeSoundCounter.value = listsoundCounter;

          List<int> listServiceCounterIDarr = List.empty(growable: true);
          for (var x in data['serviceIDSuara']) {
            listServiceCounterIDarr.add(int.parse(x.toString()));
          }
          serviceIDCounterArr.value = listServiceCounterIDarr;

          var listCounter = ref.read(allServiceProvider.notifier).state;
          List<Layanan> sc = List.empty(growable: true);

          for (var i = 0; i < listCounter.length; i++) {
            for (var j = 0; j < listServiceID.length; j++) {
              if (int.parse(listCounter[i].counterID.toString()) ==
                  listServiceID[j]) {
                sc.add(listCounter[i]);
              }
            }
          }
          selectedCounter.value = sc;

          tmr2 = Timer.periodic(Duration(seconds: 10), (timer) {
            if (listNotification.value.isNotEmpty) {
              String pesan = listNotification.value[0];
              print('Proses Sound : $pesan ');
              var notif = listNotification.value.toList();
              var splited_pesan = pesan.split(".");
              if (splited_pesan[1] == 'kd') {
                var serviceID = splited_pesan[2];
                process_sound_doctor(
                    splited_pesan[3], splited_pesan[4], serviceID);
              }
              if (splited_pesan[1] == 'fo') {
                process_sound(splited_pesan[3], splited_pesan[4]);
              }
              if (splited_pesan[1] == 'sm') {
                print('masuk sampling');
                process_sound_sampling(splited_pesan[3], splited_pesan[5]);
              }

              notif.removeAt(0);
              listNotification.value = notif;
            }
          });

          ref.read(displayProvider.notifier).listDisplayByCounterID(
              listServiceID, selectedBranch.value.mBranchID ?? "0");
        } else {
          Navigator.of(context)
              .pushNamedAndRemoveUntil(settingRoute, (route) => false);
          return;
        }
      });
      return () {
        tmr!.cancel();
        tmr2!.cancel();
      };
    }, []);
    showDialogError(BuildContext context, String msg) {
      var lstMsg = ListErrorMessage.value;
      var validation = false;

      for (var i = 0; i < lstMsg.length; i++) {
        if (lstMsg[i] == msg) {
          validation = true;
        } else {
          validation = false;
          var newMsg = [...ListErrorMessage.value];
          newMsg.add(msg);
          ListErrorMessage.value = newMsg;
        }
      }
      if (lstMsg.length == 0) {
        validation = false;
        List<String> newMsg = List.empty(growable: true);
        newMsg.add(msg.toString());
        ListErrorMessage.value = newMsg;
      }
      if (!validation) {
        // print("modal cek ");
        // print(_isThereCurrentDialogShowing(BuildContext context) =>
        // ModalRoute.of(context)?.isCurrent != true);
        var joinMsg = ListErrorMessage.value.join(",");
        myErrorDialog(context, joinMsg, 'ERROR');
      }
    }

    Timer? timer;
    ref.listen(displayProvider, (prev, next) {
      if (next is DisplayCounterDedicatedStateLoading) {
        isLoading.value = true;
      } else if (next is DisplayCounterDedicatedStateError) {
        isLoading.value = false;
        //kalau error msg connection mengaktifkan blink error
        //update error counter
        //if error counter lebih dari sama dengan 3 retry
        // kalau done erro msg blink di nonaktifkan error counter di nolkan
        if (errorMessage.value != next.message) {
          myErrorDialog(context, next.message, 'ERROR');
        }
        errorMessage.value = next.message;
        // showDialogError(context, next.message);
        // print("error" + next.message);
        Timer(const Duration(seconds: 3), () {
          errorMessage.value = "";
        });
      } else if (next is DisplayCounterDedicatedStateDone) {
        isLoading.value = false;
        listService.value = next.model;
        next.model.forEach((element) {
          listBelumDilayani.value = element.notServed;
          listSedangDilayani.value = element.served;
          listCall.value = element.call;
        });
        // print(jsonEncode(listBelumDilayani.value));
      }
    });

    getNomorAntrian(String counterID) {
      var rawCall = listCall.value;
      // print(rawCall);
      Call call = Call(
          queueID: '0',
          statusID: '0',
          queueNumber: '0',
          queueCounterID: '0',
          counterCode: '0',
          orderStatus: '0');
      for (var i = 0; i < rawCall.length; i++) {
        if (rawCall[i].queueCounterID == counterID) {
          call = rawCall[i];
        }
      }

      var rawProcess = listSedangDilayani.value;
      Served process = Served(
          queueID: '0',
          statusID: '0',
          queueNumber: '0',
          queueCounterID: '0',
          counterCode: '0',
          orderStatus: '0');

      for (var i = 0; i < rawProcess.length; i++) {
        if (rawProcess[i].queueCounterID == counterID) {
          process = rawProcess[i];
        }
      }
      if (call.queueID != '0' && process.queueID == '0') {
        return call.queueNumber;
      } else if (call.queueID == '0' && process.queueID != '0') {
        return process.queueNumber;
      } else if (call.queueID == '0' && process.queueID == '0') {
        return '-';
      } else {
        return call.queueNumber;
      }
    }

    getBlinkAntrian(String counterID) {
      var rawCall = listCall.value;
      // print(rawCall);
      Call call = Call(
          queueID: '0',
          statusID: '0',
          queueNumber: '0',
          queueCounterID: '0',
          counterCode: '0',
          orderStatus: '0');
      for (var i = 0; i < rawCall.length; i++) {
        if (rawCall[i].queueCounterID == counterID) {
          call = rawCall[i];
        }
      }

      var rawProcess = listSedangDilayani.value;
      Served process = Served(
          queueID: '0',
          statusID: '0',
          queueNumber: '0',
          queueCounterID: '0',
          counterCode: '0',
          orderStatus: '0');

      for (var i = 0; i < rawProcess.length; i++) {
        if (rawProcess[i].queueCounterID == counterID) {
          process = rawProcess[i];
        }
      }
      if (call.queueID != '0' && process.queueID == '0') {
        return true;
      } else if (call.queueID == '0' && process.queueID != '0') {
        return false;
      } else if (call.queueID == '0' && process.queueID == '0') {
        return false;
      } else {
        return true;
      }
    }

    if (tanpaMediaPromo.value == true) {
      return DisplayTanpaPromo(
        isLoading: isLoading,
        judul: judul,
        scrlCnt: scrlCnt,
        selectedCounter: selectedCounter,
        listBelumDilayani: listBelumDilayani,
        listCall: listCall,
        listSedangDilayani: listSedangDilayani,
      );
    } else {
      return WithMediaPromo(
        listBelumDilayani: listBelumDilayani,
        isLoading: isLoading,
        judul: judul,
        scrlCnt: scrlCnt,
        selectedCounter: selectedCounter,
        listCall: listCall,
        listSedangDilayani: listSedangDilayani,
      );
    }
  }
}
