import 'dart:convert';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;

import 'package:marco/controller/permission_controller.dart';
import 'package:marco/controller/project_controller.dart';
import 'package:marco/helpers/services/api_endpoints.dart';
import 'package:marco/helpers/services/storage/local_storage.dart';
import 'package:marco/helpers/services/app_logger.dart';

class AuthService {
  static const String _baseUrl = ApiEndpoints.baseUrl;
  static const Map<String, String> _headers = {
    'Content-Type': 'application/json',
  };

  static bool isLoggedIn = false;

  /// Login with email and password
  static Future<Map<String, String>?> loginUser(Map<String, dynamic> data) async {
    try {
      logSafe("Attempting login...");
      final response = await http.post(
        Uri.parse("$_baseUrl/auth/login-mobile"),
        headers: _headers,
        body: jsonEncode(data),
      );

      final responseData = jsonDecode(response.body);
      if (response.statusCode == 200 && responseData['data'] != null) {
        await _handleLoginSuccess(responseData['data']);
        return null;
      } else if (response.statusCode == 401) {
        logSafe("Invalid login credentials.", level: LogLevel.warning);
        return {"password": "Invalid email or password"};
      } else {
        logSafe("Login error: ${responseData['message']}", level: LogLevel.warning);
        return {"error": responseData['message'] ?? "Unexpected error occurred"};
      }
    } catch (e, stacktrace) {
      logSafe("Login exception", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return {"error": "Network error. Please check your connection."};
    }
  }

  /// Refresh JWT token
  static Future<bool> refreshToken() async {
    final accessToken = await LocalStorage.getJwtToken();
    final refreshToken = await LocalStorage.getRefreshToken();

    if (accessToken == null || refreshToken == null || accessToken.isEmpty || refreshToken.isEmpty) {
      logSafe("Missing access or refresh token.", level: LogLevel.warning);
      return false;
    }

    final requestBody = {
      "token": accessToken,
      "refreshToken": refreshToken,
    };

    try {
      logSafe("Refreshing token...");
      final response = await http.post(
        Uri.parse("$_baseUrl/auth/refresh-token"),
        headers: _headers,
        body: jsonEncode(requestBody),
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['success'] == true) {
        await LocalStorage.setJwtToken(data['data']['token']);
        await LocalStorage.setRefreshToken(data['data']['refreshToken']);
        await LocalStorage.setLoggedInUser(true);
        logSafe("Token refreshed successfully.");
        return true;
      } else {
        logSafe("Refresh token failed: ${data['message']}", level: LogLevel.warning);
        return false;
      }
    } catch (e, stacktrace) {
      logSafe("Token refresh exception", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return false;
    }
  }

  /// Forgot password
  static Future<Map<String, String>?> forgotPassword(String email) async {
    try {
      logSafe("Forgot password requested.");
      final response = await http.post(
        Uri.parse("$_baseUrl/auth/forgot-password"),
        headers: _headers,
        body: jsonEncode({"email": email}),
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['success'] == true) return null;
      return {"error": data['message'] ?? "Failed to send reset link."};
    } catch (e, stacktrace) {
      logSafe("Forgot password error", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return {"error": "Network error. Please check your connection."};
    }
  }

  /// Request demo
  static Future<Map<String, String>?> requestDemo(Map<String, dynamic> demoData) async {
    try {
      logSafe("Submitting demo request...");
      final response = await http.post(
        Uri.parse("$_baseUrl/market/inquiry"),
        headers: _headers,
        body: jsonEncode(demoData),
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['success'] == true) return null;
      return {"error": data['message'] ?? "Failed to submit demo request."};
    } catch (e, stacktrace) {
      logSafe("Request demo error", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return {"error": "Network error. Please check your connection."};
    }
  }

  /// Get list of industries
  static Future<List<Map<String, dynamic>>?> getIndustries() async {
    try {
      logSafe("Fetching industries list...");
      final response = await http.get(
        Uri.parse("$_baseUrl/market/industries"),
        headers: _headers,
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['success'] == true) {
        return List<Map<String, dynamic>>.from(data['data']);
      }
      return null;
    } catch (e, stacktrace) {
      logSafe("Get industries error", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return null;
    }
  }

  /// Generate MPIN
  static Future<Map<String, String>?> generateMpin({
    required String employeeId,
    required String mpin,
  }) async {
    final token = await LocalStorage.getJwtToken();

    try {
      logSafe("Generating MPIN...");
      final response = await http.post(
        Uri.parse("$_baseUrl/auth/generate-mpin"),
        headers: {
          ..._headers,
          if (token != null && token.isNotEmpty) 'Authorization': 'Bearer $token',
        },
        body: jsonEncode({"employeeId": employeeId, "mpin": mpin}),
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['success'] == true) return null;
      return {"error": data['message'] ?? "Failed to generate MPIN."};
    } catch (e, stacktrace) {
      logSafe("Generate MPIN error", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return {"error": "Network error. Please check your connection."};
    }
  }

  /// Verify MPIN
  static Future<Map<String, String>?> verifyMpin({
    required String mpin,
    required String mpinToken,
  }) async {
    final employeeInfo = LocalStorage.getEmployeeInfo();
    if (employeeInfo == null) return {"error": "Employee info not found."};

    final token = await LocalStorage.getJwtToken();

    try {
      logSafe("Verifying MPIN...");
      final response = await http.post(
        Uri.parse("$_baseUrl/auth/login-mpin"),
        headers: {
          ..._headers,
          if (token != null && token.isNotEmpty) 'Authorization': 'Bearer $token',
        },
        body: jsonEncode({
          "employeeId": employeeInfo.id,
          "mpin": mpin,
          "mpinToken": mpinToken,
        }),
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['success'] == true) return null;
      return {"error": data['message'] ?? "MPIN verification failed."};
    } catch (e, stacktrace) {
      logSafe("Verify MPIN error", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return {"error": "Network error. Please check your connection."};
    }
  }

  /// Generate OTP
  static Future<Map<String, String>?> generateOtp(String email) async {
    try {
      logSafe("Generating OTP for email...");
      final response = await http.post(
        Uri.parse("$_baseUrl/auth/send-otp"),
        headers: _headers,
        body: jsonEncode({"email": email}),
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['success'] == true) return null;
      return {"error": data['message'] ?? "Failed to generate OTP."};
    } catch (e, stacktrace) {
      logSafe("Generate OTP error", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return {"error": "Network error. Please check your connection."};
    }
  }

  /// Verify OTP and login
  static Future<Map<String, String>?> verifyOtp({
    required String email,
    required String otp,
  }) async {
    try {
      logSafe("Verifying OTP...");
      final response = await http.post(
        Uri.parse("$_baseUrl/auth/login-otp"),
        headers: _headers,
        body: jsonEncode({"email": email, "otp": otp}),
      );

      final data = jsonDecode(response.body);
      if (response.statusCode == 200 && data['data'] != null) {
        await _handleLoginSuccess(data['data']);
        return null;
      }
      return {"error": data['message'] ?? "OTP verification failed."};
    } catch (e, stacktrace) {
      logSafe("Verify OTP error", level: LogLevel.error, error: e, stackTrace: stacktrace);
      return {"error": "Network error. Please check your connection."};
    }
  }

  /// Handle login success flow
 static Future<void> _handleLoginSuccess(Map<String, dynamic> data) async {
  logSafe("Processing login success...");

  final jwtToken = data['token'];
  final refreshToken = data['refreshToken'];
  final mpinToken = data['mpinToken'];

  // Save tokens
  await LocalStorage.setJwtToken(jwtToken);
  await LocalStorage.setLoggedInUser(true);

  if (refreshToken != null) {
    await LocalStorage.setRefreshToken(refreshToken);
  }

  if (mpinToken != null && mpinToken.isNotEmpty) {
    await LocalStorage.setMpinToken(mpinToken);
    await LocalStorage.setIsMpin(true);
  } else {
    await LocalStorage.setIsMpin(false);
    await LocalStorage.removeMpinToken();
  }

  // Inject controllers if not already registered
  if (!Get.isRegistered<PermissionController>()) {
    Get.put(PermissionController());
    logSafe("✅ PermissionController injected after login.");
  }

  if (!Get.isRegistered<ProjectController>()) {
    Get.put(ProjectController(), permanent: true);
    logSafe("✅ ProjectController injected after login.");
  }

  // Load data into controllers
  await Get.find<PermissionController>().loadData(jwtToken);
  await Get.find<ProjectController>().fetchProjects();

  isLoggedIn = true;
  logSafe("✅ Login flow completed and controllers initialized.");
}
}