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

import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/data/common/dio_error_handler.dart';
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_chicken/data/models/response/user_info/user_info_model.dart';
import 'package:rasadyar_chicken/data/models/response/user_profile_model/user_profile_model.dart';
import 'package:rasadyar_chicken/data/repositories/auth/auth_repository.dart';
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/presentation/widget/captcha/logic.dart';
import 'package:rasadyar_core/core.dart';

enum AuthType { useAndPass, otp }

enum AuthStatus { init }

enum OtpStatus { init, sent, verified, reSend }

class AuthLogic extends GetxController with GetTickerProviderStateMixin {
  GlobalKey<FormState> formKey = GlobalKey<FormState>();
  late AnimationController _textAnimationController;
  late Animation<double> textAnimation;
  RxBool showCard = false.obs;
  RxBool rememberMe = false.obs;

  Rx<GlobalKey<FormState>> formKeyOtp = GlobalKey<FormState>().obs;
  Rx<GlobalKey<FormState>> formKeySentOtp = GlobalKey<FormState>().obs;
  Rx<TextEditingController> usernameController = TextEditingController().obs;
  Rx<TextEditingController> passwordController = TextEditingController().obs;
  Rx<TextEditingController> phoneOtpNumberController = TextEditingController().obs;
  Rx<TextEditingController> otpCodeController = TextEditingController().obs;

  var captchaController = Get.find<CaptchaWidgetLogic>();

  RxnString phoneNumber = RxnString(null);
  RxBool isLoading = false.obs;
  RxBool isDisabled = true.obs;

  GService gService = Get.find<GService>();
  TokenStorageService tokenStorageService = Get.find<TokenStorageService>();

  Rx<AuthType> authType = AuthType.useAndPass.obs;
  Rx<AuthStatus> authStatus = AuthStatus.init.obs;
  Rx<OtpStatus> otpStatus = OtpStatus.init.obs;
  RxnString deviceName = RxnString(null);

  RxInt secondsRemaining = 120.obs;
  Timer? _timer;

  AuthRepository authRepository = diChicken.get<AuthRepository>();

  final Module _module = Get.arguments;

  @override
  void onInit() {
    super.onInit();
    _textAnimationController =
        AnimationController(vsync: this, duration: const Duration(milliseconds: 1200))
          ..repeat(reverse: true, count: 2).whenComplete(() {
            showCard.value = true;
          });

    textAnimation = CurvedAnimation(parent: _textAnimationController, curve: Curves.easeInOut);

    initUserPassData();
    getDeviceModel();
  }

  @override
  void onClose() {
    _textAnimationController.dispose();
    _timer?.cancel();
    super.onClose();
  }

  void startTimer() {
    _timer?.cancel();
    secondsRemaining.value = 120;

    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (secondsRemaining.value > 0) {
        secondsRemaining.value--;
      } else {
        timer.cancel();
      }
    });
  }

  void stopTimer() {
    _timer?.cancel();
  }

  String get timeFormatted {
    final minutes = secondsRemaining.value ~/ 60;
    final seconds = secondsRemaining.value % 60;
    return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
  }

  bool _isFormValid() {
    final isCaptchaValid = captchaController.formKey.currentState?.validate() ?? false;
    final isFormValid = formKey.currentState?.validate() ?? false;
    return isCaptchaValid && isFormValid;
  }

  Future<void> submitLoginForm() async {
    if (!_isFormValid()) return;
    AuthRepository authTmp = diChicken.get<AuthRepository>();
    isLoading.value = true;
    await safeCall<UserProfileModel?>(
      call: () => authTmp.login(
        authRequest: {
          "username": usernameController.value.text,
          "password": passwordController.value.text,
        },
      ),
      onSuccess: (result) async {
        await gService.saveSelectedModule(_module);
        await tokenStorageService.saveModule(_module);
        await tokenStorageService.saveAccessToken(_module, result?.accessToken ?? '');
        await tokenStorageService.saveRefreshToken(_module, result?.accessToken ?? '');
        var tmpRoles = result?.role
            ?.where((element) => element == 'PoultryScience' || element == 'Steward')
            .toList();
        await tokenStorageService.saveRoles(_module, tmpRoles ?? []);
        if (rememberMe.value) {
          await tokenStorageService.saveUserPass(
            _module,
            usernameController.value.text,
            passwordController.value.text,
          );
        }

        authRepository.submitUserInfo(
          phone: usernameController.value.text,
          deviceName: deviceName.value,
        );

        if (tmpRoles!.length > 1) {
          Get.offAndToNamed(ChickenRoutes.role);
        } else {
          Get.offAllNamed(ChickenRoutes.initSteward);
        }
      },
      onError: (error, stackTrace) {
        if (error is DioException) {
          diChicken.get<DioErrorHandler>().handle(error);
          if ((error.type == DioExceptionType.unknown) ||
              (error.type == DioExceptionType.connectionError)) {
            getUserInfo(usernameController.value.text);
          }
        }
        captchaController.getCaptcha();
      },
    );
    isLoading.value = false;
  }

  Future<void> getUserInfo(String value) async {
    isLoading.value = true;
    await safeCall<UserInfoModel?>(
      call: () async => await authRepository.getUserInfo(value),
      onSuccess: (result) async {
        if (result != null) {
          await newSetupAuthDI(result.backend ?? '');
          await diChicken.allReady();
        }
      },
      onError: (error, stackTrace) {
        if (error is DioException) {
          diChicken.get<DioErrorHandler>().handle(error);
        }
        captchaController.getCaptcha();
      },
    );
    isLoading.value = false;
  }

  void initUserPassData() {
    UserLocalModel? userLocalModel = tokenStorageService.getUserLocal(Module.chicken);
    if (userLocalModel?.username != null && userLocalModel?.password != null) {
      usernameController.value.text = userLocalModel?.username ?? '';
      passwordController.value.text = userLocalModel?.password ?? '';
      rememberMe.value = true;
    }
  }

  Future<void> getDeviceModel() async {
    final deviceInfo = DeviceInfoPlugin();

    if (Platform.isAndroid) {
      final info = await deviceInfo.androidInfo;
      print('Device: ${info.manufacturer} ${info.model}');
      print('Android version: ${info.version.release}');
      deviceName.value =
          'Device:${info.manufacturer} Model:${info.model} version ${info.version.release}';
    } else if (Platform.isIOS) {
      final info = await deviceInfo.iosInfo;
      print('Device: ${info.utsname.machine} (${info.name})');
      print('System version: ${info.systemVersion}');
      deviceName.value =
          'Device:${info.utsname.machine} Model:${info.model} version ${info.systemVersion}';
    } else {
      print('Unsupported platform');
    }
  }
}
