import 'dart:async';
import 'package:base_project/repository/auth_repo.dart';
import 'package:base_project/routes/route_names.dart';
import 'package:base_project/utils/flushbar_messages/flush_message_util.dart';
import 'package:base_project/utils/managers/user_manager.dart';
import 'package:base_project/utils/toast_messages/toast_message_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

class AuthViewModel extends ChangeNotifier {
  final AuthRepo _authRepo = AuthRepo();
  bool _isLoading = false;
  bool get isLoading => _isLoading;

  setLoading(bool value) {
    _isLoading = value;
    notifyListeners();
  }

  Timer? _timer;
  int _start = 30;
  bool _isResendEnabled = false;

  int get start => _start;
  bool get isResendEnabled => _isResendEnabled;

  void startTimer() {
    _isResendEnabled = false;
    _start = 30; // Set the timer duration (in seconds)
    _timer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
      if (_start == 0) {
        _timer?.cancel();
        _isResendEnabled = true;
        notifyListeners();
      } else {
        _start--;
        print(_start);
        notifyListeners();
      }
    });
  }

  var accId = "";
  var uEmail = "";

  Future<void> login(BuildContext context, dynamic data) async {
    setLoading(true);

    try {
      final value = await _authRepo.loginApi(data);
      print('Value is -$value');

      // Check the response structure
      if (value['operationStatus'] == 'SUCCESS') {
        final item = value['item'];
        await UserManager().setUser(item);
        // Try to persist sys account from login response if present
        try {
          final dynamic accountCandidate =
              item['sysAccount'] ?? item['account'] ?? item['sys_account'];
          if (accountCandidate is Map<String, dynamic>) {
            await UserManager().setAccount(accountCandidate);
          }
        } catch (_) {}

        final prefs = await SharedPreferences.getInstance();
        prefs.setBool('isLoggedIn', true);
        // Handle successful login
        ToastMessageUtil.showToast(
            message: 'Logged in as ${value['item']['email']}',
            toastType: ToastType.general);
        // nav to home
        Navigator.pushReplacementNamed(context, RouteNames.homeView);
      } else {
        print('Error got ');

        // Handle login failure with backend message if available
        final backendMessage = (value is Map)
            ? (value['operationMessage'] ?? value['message'] ?? value['msg'])
            : null;
        final message = (backendMessage?.toString().trim().isNotEmpty == true)
            ? backendMessage.toString()
            : "Failed!!  Email or Password is incorrect";

        FlushBarMessageUtil.showFlushBar(
          context: context,
          message: message,
          flushBarType: FlushBarType.error,
        );
      }
    } catch (error, stackTrace) {
      print("Error -$error");
      print("st -$stackTrace");
      // Handle any other errors
      FlushBarMessageUtil.showFlushBar(
        context: context,
        message: error.toString(),
        flushBarType: FlushBarType.error,
      );
    } finally {
      setLoading(false);
    }
  }

  Future<void> signUp(BuildContext context, dynamic data) async {
    setLoading(true);
    final createUserData = {...data, 'account_id': accId};
    print("CreateUserData--$createUserData");

    _authRepo.createUserApi(createUserData).then((value) {
      print(value);
      ToastMessageUtil.showToast(
          message: "Account Created", toastType: ToastType.success);
      setLoading(false);
      Navigator.pushReplacementNamed(context, RouteNames.loginView);
    }).onError(
      (error, stackTrace) {
        print(error);
        print(stackTrace);
        FlushBarMessageUtil.showFlushBar(
            context: context,
            message: error.toString(),
            flushBarType: FlushBarType.error);
        setLoading(false);
      },
    );
  }

  // New method for combined registration flow (account + user)
  Future<void> signUpWithAccountCreation(
      BuildContext context, dynamic data) async {
    setLoading(true);

    try {
      // Step 1: Create account with just email and password
      final accountData = {
        "email": data["email"],
      };

      print("Creating account with data: $accountData");
      final accountResponse = await _authRepo.createAcApi(accountData);
      print("Account creation response: $accountResponse");

      // Extract account ID from response
      final accountId = accountResponse['account_id']?.toString();
      if (accountId == null) {
        throw Exception("Account ID not received from server");
      }

      // Step 2: Create user with account ID
      final createUserData = {...data, 'account_id': accountId};

      print("Creating user with data: $createUserData");
      final userResponse = await _authRepo.createUserApi(createUserData);
      print("User creation response: $userResponse");

      ToastMessageUtil.showToast(
          message: "Account Created Successfully",
          toastType: ToastType.success);

      // Navigate to login
      Navigator.pushReplacementNamed(context, RouteNames.loginView);
    } catch (error, stackTrace) {
      print("SignUp error: $error");
      print("Stack trace: $stackTrace");

      String errorMessage = "Registration failed. Please try again.";
      if (error.toString().contains('already exist')) {
        errorMessage = "Email already exists. Please use a different email.";
      } else if (error.toString().contains('account_id')) {
        errorMessage = "Account creation failed. Please try again.";
      }

      FlushBarMessageUtil.showFlushBar(
          context: context,
          message: errorMessage,
          flushBarType: FlushBarType.error);
    } finally {
      setLoading(false);
    }
  }

  Future<void> createAcc(BuildContext context, dynamic data) async {
    setLoading(true);
    _authRepo.createAcApi(data).then(
      (value) {
        print("Value--$value");
        accId = value['account_id'].toString();
        setLoading(false);
        ToastMessageUtil.showToast(
            message: "Success creating account", toastType: ToastType.success);
        // Navigator.pushNamed(context, RouteNames.signUp,arguments: uEmail);
      },
    ).onError(
      (error, stackTrace) {
        print("error--$error");
        setLoading(false);
        ToastMessageUtil.showToast(
            message: "Error registering your account",
            toastType: ToastType.error);
      },
    );
  }

  Future<void> getOtp(BuildContext context, dynamic data) async {
    setLoading(true);

    try {
      final value = await _authRepo.getOtpApi(data);
      print(value);

      // Handle non-exception responses like { msg: "... already exist" }
      if (value is Map) {
        final map = Map<String, dynamic>.from(value);
        final message = (map['msg'] ?? map['message'] ?? '').toString();
        final operationStatus = (map['operationStatus'] ?? '').toString();
        final otpSent = (map['otp_sent'] == true) || (map['otpSent'] == true);

        // Block when backend says email already exists
        if (message.toLowerCase().contains('already exist')) {
          ToastMessageUtil.showToast(
            message: 'Email already exists',
            toastType: ToastType.error,
          );
          return; // do not navigate
        }

        // Consider success scenarios (handle variants like "Otp send successfully")
        final lowerMsg = message.toLowerCase();
        final messageLooksSuccess = lowerMsg.contains('otp sent') ||
            lowerMsg.contains('sent successfully') ||
            (lowerMsg.contains('otp') && lowerMsg.contains('success')) ||
            lowerMsg.contains('send successfully');

        if (operationStatus == 'SUCCESS' || otpSent || messageLooksSuccess) {
          ToastMessageUtil.showToast(
            message: message.isNotEmpty ? message : 'OTP sent successfully',
            toastType: ToastType.success,
          );
          // Start resend countdown when OTP is sent
          startTimer();
          Navigator.pushNamed(
            context,
            RouteNames.verifyOtpView,
            arguments: {'email': data['email']},
          );
          return;
        }

        // Fallback: show backend message if present
        if (message.isNotEmpty) {
          ToastMessageUtil.showToast(
            message: message,
            toastType: ToastType.error,
          );
          return;
        }
      }

      // Unknown response structure
      ToastMessageUtil.showToast(
        message: 'Failed to send OTP',
        toastType: ToastType.error,
      );
    } catch (error) {
      // Handle any other exceptions
      print("getOtp error: $error");
      final msg = error.toString();
      String uiMessage = 'Failed to send OTP';
      if (msg.contains('already exist') || msg.contains('already exists')) {
        uiMessage = 'Email already exists';
      } else if (msg.contains('invalid') || msg.contains('Invalid')) {
        uiMessage = 'Invalid email address';
      } else if (msg.contains('timeout')) {
        uiMessage = 'Request timed out. Please try again.';
      }

      ToastMessageUtil.showToast(
        message: uiMessage,
        toastType: ToastType.error,
      );
    } finally {
      setLoading(false);
    }
  }

  Future<void> resendOtp(BuildContext context, dynamic data) async {
    startTimer();
    await _authRepo.resendOtpApi(data).then((value) {
      print(value);
      ToastMessageUtil.showToast(
        message: "OTP resend successfully",
        toastType: ToastType.success,
      );
    }).onError(
      (error, stackTrace) {
        print(error);
        ToastMessageUtil.showToast(
          message: "Failed to resend OTP",
          toastType: ToastType.error,
        );
      },
    );
  }

  /// Returns null on success, or a human-readable error message on failure
  Future<String?> verifyOtp(BuildContext context, dynamic queryParams) async {
    print("Verifying otp");
    setLoading(true);
    try {
      final value = await _authRepo.verifyOtpApi(queryParams);
      print(value);

      // Backend returns 200 with EntityResponse("OTP Verified")
      // and 400 with EntityResponse("Wrong OTP") or MessageResponse("... not exist")
      if (value is Map) {
        final map = Map<String, dynamic>.from(value);
        final message = (map['msg'] ?? map['message'] ?? '').toString();
        final lower = message.toLowerCase();

        if (lower.contains('otp verified')) {
          ToastMessageUtil.showToast(
            message: 'OTP Verified',
            toastType: ToastType.success,
          );
          uEmail = queryParams['email'];
          cancelTimer();
          return null;
        }

        if (lower.contains('wrong otp')) {
          ToastMessageUtil.showToast(
            message: 'Wrong OTP',
            toastType: ToastType.error,
          );
          return 'Wrong OTP';
        }

        if (lower.contains('not exist')) {
          ToastMessageUtil.showToast(
            message: 'User not found',
            toastType: ToastType.error,
          );
          return 'User not found';
        }

        // Fallback: show message if present
        if (message.isNotEmpty) {
          ToastMessageUtil.showToast(
            message: message,
            toastType: ToastType.error,
          );
          return message;
        }
      }

      ToastMessageUtil.showToast(
        message: 'OTP verification failed',
        toastType: ToastType.error,
      );
      return 'OTP verification failed';
    } catch (error) {
      print(error);
      ToastMessageUtil.showToast(
        message: "OTP verification failed",
        toastType: ToastType.error,
      );
      return 'OTP verification failed';
    } finally {
      setLoading(false);
    }
  }

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

  @override
  void dispose() {
    cancelTimer(); // Ensure the timer is cancelled
    super.dispose();
  }
}
