import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:on_field_work/helpers/services/api_endpoints.dart';
import 'package:on_field_work/helpers/services/storage/local_storage.dart';
import 'package:on_field_work/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;
  /* -------------------------------------------------------------------------- */
  /*                                Logout API                                  */
  /* -------------------------------------------------------------------------- */
  static Future<bool> logoutApi(String refreshToken, String fcmToken) async {
    try {
      final body = {
        "refreshToken": refreshToken,
        "fcmToken": fcmToken,
      };

      final response = await _post("/auth/logout", body);

      if (response != null && response['statusCode'] == 200) {
        logSafe("✅ Logout API successful");
        return true;
      }

      logSafe("⚠️ Logout API failed: ${response?['message']}",
          level: LogLevel.warning);
      return false;
    } catch (e, st) {
      _handleError("Logout API error", e, st);
      return false;
    }
  }

  /* -------------------------------------------------------------------------- */
  /*                               Public Methods                               */
  /* -------------------------------------------------------------------------- */

  static Future<bool> registerDeviceToken(String fcmToken) async {
    final token = await LocalStorage.getJwtToken();
    if (token == null || token.isEmpty) {
      logSafe("❌ Cannot register device token: missing JWT token",
          level: LogLevel.warning);
      return false;
    }

    final body = {"fcmToken": fcmToken};
    final headers = {
      ..._headers,
      'Authorization': 'Bearer $token',
    };
    final endpoint = "$_baseUrl/auth/set/device-token";

    // 🔹 Log request details
    logSafe("📡 Device Token API Request");
    logSafe("➡️ Endpoint: $endpoint");
    logSafe("➡️ Headers: ${jsonEncode(headers)}");
    logSafe("➡️ Payload: ${jsonEncode(body)}");

    final data = await _post("/auth/set/device-token", body, authToken: token);

    if (data != null && data['success'] == true) {
      logSafe("✅ Device token registered successfully.");
      return true;
    }
    logSafe("⚠️ Failed to register device token: ${data?['message']}",
        level: LogLevel.warning);
    return false;
  }

  static Future<Map<String, String>?> loginUser(
      Map<String, dynamic> data) async {
    logSafe("Attempting login...");
    logSafe("Login payload (raw): $data");
    logSafe("Login payload (JSON): ${jsonEncode(data)}");

    final responseData = await _post("/auth/app/login", data);
    if (responseData == null)
      return {"error": "Network error. Please check your connection."};

    if (responseData['data'] != null) {
      await _handleLoginSuccess(responseData['data']);
      return null;
    }
    if (responseData['statusCode'] == 401) {
      return {"password": "Invalid email or password"};
    }
    return {"error": responseData['message'] ?? "Unexpected error occurred"};
  }

  static Future<bool> refreshToken() async {
    final accessToken =  LocalStorage.getJwtToken();
    final refreshToken =  LocalStorage.getRefreshToken();

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

    final body = {"token": accessToken, "refreshToken": refreshToken};
    final data = await _post("/auth/refresh-token", body);
    if (data != null && data['success'] == true) {
      await LocalStorage.setJwtToken(data['data']['token']);
      await LocalStorage.setRefreshToken(data['data']['refreshToken']);
      await LocalStorage.setLoggedInUser(true);
      logSafe("Token refreshed successfully.");

      // 🔹 Retry FCM token registration after token refresh
      final newFcmToken =  LocalStorage.getFcmToken();
      if (newFcmToken?.isNotEmpty ?? false) {
        final success = await registerDeviceToken(newFcmToken!);
        logSafe(
            success
                ? "✅ FCM token re-registered after JWT refresh."
                : "⚠️ Failed to register FCM token after JWT refresh.",
            level: success ? LogLevel.info : LogLevel.warning);
      }

      return true;
    }
    logSafe("Refresh token failed: ${data?['message']}",
        level: LogLevel.warning);
    return false;
  }

  static Future<Map<String, String>?> forgotPassword(String email) =>
      _wrapErrorHandling(() => _post("/auth/forgot-password", {"email": email}),
          successCondition: (data) => data['success'] == true,
          defaultError: "Failed to send reset link.");

  static Future<Map<String, String>?> requestDemo(
          Map<String, dynamic> demoData) =>
      _wrapErrorHandling(() => _post("/market/inquiry", demoData),
          successCondition: (data) => data['success'] == true,
          defaultError: "Failed to submit demo request.");

  static Future<List<Map<String, dynamic>>?> getIndustries() async {
    final data = await _get("/market/industries");
    if (data != null && data['success'] == true) {
      return List<Map<String, dynamic>>.from(data['data']);
    }
    return null;
  }

  static Future<Map<String, String>?> generateMpin({
    required String employeeId,
    required String mpin,
  }) =>
      _wrapErrorHandling(
        () async {
          final token =  LocalStorage.getJwtToken();
          return _post(
            "/auth/generate-mpin",
            {"employeeId": employeeId, "mpin": mpin},
            authToken: token,
          );
        },
        successCondition: (data) => data['success'] == true,
        defaultError: "Failed to generate MPIN.",
      );

  static Future<Map<String, String>?> verifyMpin({
    required String mpin,
    required String mpinToken,
    required String fcmToken,
  }) =>
      _wrapErrorHandling(
        () async {
          final employeeInfo = LocalStorage.getEmployeeInfo();
          if (employeeInfo == null) return null;
          final token = await LocalStorage.getJwtToken();
          return _post(
            "/auth/login-mpin",
            {
              "employeeId": employeeInfo.id,
              "mpin": mpin,
              "mpinToken": mpinToken,
              "fcmToken": fcmToken,
            },
            authToken: token,
          );
        },
        successCondition: (data) => data['success'] == true,
        defaultError: "MPIN verification failed.",
      );

  static Future<Map<String, String>?> generateOtp(String email) =>
      _wrapErrorHandling(() => _post("/auth/send-otp", {"email": email}),
          successCondition: (data) => data['success'] == true,
          defaultError: "Failed to generate OTP.");

  static Future<Map<String, String>?> verifyOtp({
    required String email,
    required String otp,
  }) async {
    final data = await _post("/auth/login-otp", {"email": email, "otp": otp});
    if (data != null && data['data'] != null) {
      await _handleLoginSuccess(data['data']);
      return null;
    }
    return {"error": data?['message'] ?? "OTP verification failed."};
  }

  /* -------------------------------------------------------------------------- */
  /*                             Private Utilities                              */
  /* -------------------------------------------------------------------------- */

  static Future<Map<String, dynamic>?> _post(
    String path,
    Map<String, dynamic> body, {
    String? authToken,
  }) async {
    try {
      final headers = {
        ..._headers,
        if (authToken?.isNotEmpty ?? false)
          'Authorization': 'Bearer $authToken',
      };
      final response = await http.post(Uri.parse("$_baseUrl$path"),
          headers: headers, body: jsonEncode(body));
      return {
        ...jsonDecode(response.body),
        "statusCode": response.statusCode,
      };
    } catch (e, st) {
      _handleError("$path POST error", e, st);
      return null;
    }
  }

  static Future<Map<String, dynamic>?> _get(
    String path, {
    String? authToken,
  }) async {
    try {
      final headers = {
        ..._headers,
        if (authToken?.isNotEmpty ?? false)
          'Authorization': 'Bearer $authToken',
      };
      final response =
          await http.get(Uri.parse("$_baseUrl$path"), headers: headers);
      return {
        ...jsonDecode(response.body),
        "statusCode": response.statusCode,
      };
    } catch (e, st) {
      _handleError("$path GET error", e, st);
      return null;
    }
  }

  static Future<Map<String, String>?> _wrapErrorHandling(
    Future<Map<String, dynamic>?> Function() request, {
    required bool Function(Map<String, dynamic> data) successCondition,
    required String defaultError,
  }) async {
    final data = await request();
    if (data != null && successCondition(data)) return null;
    return {"error": data?['message'] ?? defaultError};
  }

  static void _handleError(String message, Object error, StackTrace st) {
    logSafe(message, level: LogLevel.error, error: error, stackTrace: st);
  }

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

    await LocalStorage.setJwtToken(data['token']);
    await LocalStorage.setLoggedInUser(true);

    if (data['refreshToken'] != null) {
      await LocalStorage.setRefreshToken(data['refreshToken']);
    }

    if (data['mpinToken']?.isNotEmpty ?? false) {
      await LocalStorage.setMpinToken(data['mpinToken']);
      await LocalStorage.setIsMpin(true);
    } else {
      await LocalStorage.setIsMpin(false);
      await LocalStorage.removeMpinToken();
    }
    isLoggedIn = true;
    logSafe("✅ Login flow completed and controllers initialized.");
  }
}
