import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:mocktail/mocktail.dart';
import 'package:rasadyar_inspection/presentation/pages/auth/logic.dart';
import 'package:rasadyar_inspection/data/repositories/auth/auth_repository_imp.dart';
import 'package:rasadyar_inspection/presentation/widget/captcha/logic.dart';
import 'package:rasadyar_core/core.dart';

class MockAuthRepositoryImpl extends Mock implements AuthRepositoryImpl {}

class MockTokenStorageService extends Mock implements TokenStorageService {}

class MockCaptchaWidgetLogic extends GetxController with Mock implements CaptchaWidgetLogic {
  @override
  GlobalKey<FormState> formKey = GlobalKey<FormState>();
}

class MockTickerProvider extends Mock implements TickerProvider {
  @override
  Ticker createTicker(TickerCallback onTick) {
    return Ticker(onTick);
  }
}

void main() {
  group('AuthLogic Tests', () {
    late AuthLogic authLogic;
    late MockAuthRepositoryImpl mockAuthRepository;
    late MockTokenStorageService mockTokenService;
    late MockCaptchaWidgetLogic mockCaptchaController;

    setUp(() {
      mockAuthRepository = MockAuthRepositoryImpl();
      mockTokenService = MockTokenStorageService();
      mockCaptchaController = MockCaptchaWidgetLogic();

      Get.put<TokenStorageService>(mockTokenService);
      Get.put<CaptchaWidgetLogic>(mockCaptchaController);

      // Mock the Get.arguments to return a Module
      Get.testMode = true;
    });

    tearDown(() {
      Get.reset();
    });

    test('should initialize with correct default values', () {
      // Arrange & Act
      authLogic = AuthLogic();

      // Assert
      expect(authLogic.showCard.value, false);
      expect(authLogic.rememberMe.value, false);
      expect(authLogic.isLoading.value, false);
      expect(authLogic.isDisabled.value, true);
      expect(authLogic.authType.value, AuthType.useAndPass);
      expect(authLogic.authStatus.value, AuthStatus.init);
      expect(authLogic.otpStatus.value, OtpStatus.init);
      expect(authLogic.secondsRemaining.value, 120);
      expect(authLogic.phoneNumber.value, null);
    });

    test('should have correct controllers initialized', () {
      // Arrange & Act
      authLogic = AuthLogic();

      // Assert
      expect(authLogic.usernameController.value, isA<TextEditingController>());
      expect(authLogic.passwordController.value, isA<TextEditingController>());
      expect(authLogic.phoneOtpNumberController.value, isA<TextEditingController>());
      expect(authLogic.otpCodeController.value, isA<TextEditingController>());
      expect(authLogic.formKey, isA<GlobalKey<FormState>>());
    });

    test('should start timer correctly', () {
      // Arrange
      authLogic = AuthLogic();

      // Act
      authLogic.startTimer();

      // Assert
      expect(authLogic.secondsRemaining.value, 120);
    });

    test('should format time correctly', () {
      // Arrange
      authLogic = AuthLogic();

      // Act
      authLogic.secondsRemaining.value = 90; // 1 minute 30 seconds
      String formatted = authLogic.timeFormatted;

      // Assert
      expect(formatted, '01:30');

      // Act
      authLogic.secondsRemaining.value = 5; // 5 seconds
      formatted = authLogic.timeFormatted;

      // Assert
      expect(formatted, '00:05');
    });

    test('should stop timer correctly', () {
      // Arrange
      authLogic = AuthLogic();
      authLogic.startTimer();

      // Act
      authLogic.stopTimer();

      // The timer should be cancelled, but we can't directly test this
      // We can test that the method doesn't throw an error
      expect(() => authLogic.stopTimer(), returnsNormally);
    });

    test('should update authType correctly', () {
      // Arrange
      authLogic = AuthLogic();

      // Act
      authLogic.authType.value = AuthType.otp;

      // Assert
      expect(authLogic.authType.value, AuthType.otp);
    });

    test('should update otpStatus correctly', () {
      // Arrange
      authLogic = AuthLogic();

      // Act
      authLogic.otpStatus.value = OtpStatus.sent;

      // Assert
      expect(authLogic.otpStatus.value, OtpStatus.sent);

      // Act
      authLogic.otpStatus.value = OtpStatus.verified;

      // Assert
      expect(authLogic.otpStatus.value, OtpStatus.verified);
    });

    test('should update phoneNumber correctly', () {
      // Arrange
      authLogic = AuthLogic();

      // Act
      authLogic.phoneNumber.value = '09123456789';

      // Assert
      expect(authLogic.phoneNumber.value, '09123456789');
    });

    test('should update loading state correctly', () {
      // Arrange
      authLogic = AuthLogic();

      // Act
      authLogic.isLoading.value = true;

      // Assert
      expect(authLogic.isLoading.value, true);

      // Act
      authLogic.isLoading.value = false;

      // Assert
      expect(authLogic.isLoading.value, false);
    });

    test('should update rememberMe correctly', () {
      // Arrange
      authLogic = AuthLogic();

      // Act
      authLogic.rememberMe.value = true;

      // Assert
      expect(authLogic.rememberMe.value, true);
    });

    test('should have correct dependencies injected', () {
      // Arrange & Act
      authLogic = AuthLogic();

      // Assert
      expect(authLogic.tokenStorageService, isA<TokenStorageService>());
      expect(authLogic.captchaController, isA<CaptchaWidgetLogic>());
      expect(authLogic.authRepository, isA<AuthRepositoryImpl>());
    });

    test('should dispose timer on close', () {
      // Arrange
      authLogic = AuthLogic();
      authLogic.startTimer();

      // Act
      authLogic.onClose();

      // Timer should be cancelled
      expect(() => authLogic.onClose(), returnsNormally);
    });
  });
}
