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

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';
import 'package:on_field_work/helpers/services/auth_service.dart';
import 'package:on_field_work/model/tenant/tenant_list_model.dart';

/// Abstract interface for tenant service functionality
abstract class ITenantService {
  Future<List<Map<String, dynamic>>?> getTenants({bool hasRetried = false});
  Future<bool> selectTenant(String tenantId, {bool hasRetried = false});
}

/// Tenant API service
class TenantService implements ITenantService {
  static const String _baseUrl = ApiEndpoints.baseUrl;
  static const Map<String, String> _headers = {
    'Content-Type': 'application/json',
  };

  /// Currently selected tenant
  static Tenant? currentTenant;

  /// Set the selected tenant
  static void setSelectedTenant(Tenant tenant) {
    currentTenant = tenant;
  }

  /// Check if tenant is selected
  static bool get isTenantSelected => currentTenant != null;

  /// Build authorized headers
  static Future<Map<String, String>> _authorizedHeaders() async {
    final token = await LocalStorage.getJwtToken();
    if (token == null || token.isEmpty) {
      throw Exception('Missing JWT token');
    }
    return {..._headers, 'Authorization': 'Bearer $token'};
  }

  /// Handle API errors
  static void _handleApiError(
      http.Response response, dynamic data, String context) {
    final message = data['message'] ?? 'Unknown error';
    final level =
        response.statusCode >= 500 ? LogLevel.error : LogLevel.warning;
    logSafe("❌ $context failed: $message [Status: ${response.statusCode}]",
        level: level);
  }

  /// Log exceptions
  static void _logException(dynamic e, dynamic st, String context) {
    logSafe("❌ $context exception",
        level: LogLevel.error, error: e, stackTrace: st);
  }

  @override
  Future<List<Map<String, dynamic>>?> getTenants(
      {bool hasRetried = false}) async {
    try {
      final headers = await _authorizedHeaders();

      final response = await http.get(
        Uri.parse("$_baseUrl/auth/get/user/tenants"),
        headers: headers,
      );

      // ✅ Handle empty response BEFORE decoding
      if (response.body.isEmpty || response.body.trim().isEmpty) {
        logSafe("❌ Empty tenant response — auto logout");
        await LocalStorage.logout();
        return null;
      }

      Map<String, dynamic> data;
      try {
        data = jsonDecode(response.body);
      } catch (e) {
        logSafe("❌ Invalid JSON in tenant response — auto logout");
        await LocalStorage.logout();
        return null;
      }

      // SUCCESS CASE
      if (response.statusCode == 200 && data['success'] == true) {
        final list = data['data'];
        if (list is! List) return null;
        return List<Map<String, dynamic>>.from(list);
      }

      // TOKEN EXPIRED
      if (response.statusCode == 401 && !hasRetried) {
        final refreshed = await AuthService.refreshToken();
        if (refreshed) return getTenants(hasRetried: true);
        return null;
      }

      _handleApiError(response, data, "Fetching tenants");
      return null;
    } catch (e, st) {
      _logException(e, st, "Get Tenants API");
      return null;
    }
  }

  @override
  Future<bool> selectTenant(String tenantId, {bool hasRetried = false}) async {
    try {
      final headers = await _authorizedHeaders();
      logSafe(
          "➡️ POST $_baseUrl/auth/select-tenant/$tenantId\nHeaders: $headers",
          level: LogLevel.info);

      final response = await http.post(
        Uri.parse("$_baseUrl/auth/select-tenant/$tenantId"),
        headers: headers,
      );
      final data = jsonDecode(response.body);

      logSafe(
          "⬅️ Response: ${jsonEncode(data)} [Status: ${response.statusCode}]",
          level: LogLevel.info);

      if (response.statusCode == 200 && data['success'] == true) {
        await LocalStorage.setJwtToken(data['data']['token']);
        await LocalStorage.setRefreshToken(data['data']['refreshToken']);
        logSafe("✅ Tenant selected successfully. Tokens updated.");

        // 🔥 Refresh projects when tenant changes
        try {
          final projectController = Get.find<ProjectController>();
          projectController.clearProjects();
          projectController.fetchProjects();
        } catch (_) {
          logSafe("⚠️ ProjectController not found while refreshing projects");
        }

        // 🔹 Register FCM token after tenant selection
        final fcmToken = LocalStorage.getFcmToken();
        if (fcmToken?.isNotEmpty ?? false) {
          final success = await AuthService.registerDeviceToken(fcmToken!);
          logSafe(
              success
                  ? "✅ FCM token registered after tenant selection."
                  : "⚠️ Failed to register FCM token after tenant selection.",
              level: success ? LogLevel.info : LogLevel.warning);
        }

        return true;
      }

      if (response.statusCode == 401 && !hasRetried) {
        logSafe("⚠️ Unauthorized while selecting tenant. Refreshing token...",
            level: LogLevel.warning);
        final refreshed = await AuthService.refreshToken();
        if (refreshed) return selectTenant(tenantId, hasRetried: true);
        logSafe("❌ Token refresh failed while selecting tenant.",
            level: LogLevel.error);
        return false;
      }

      _handleApiError(response, data, "Selecting tenant");
      return false;
    } catch (e, st) {
      _logException(e, st, "Select Tenant API");
      return false;
    }
  }
}
