import 'package:flutter/material.dart';
import 'package:qpay/http/http.dart';
import 'package:qpay/models/api_response.dart';
import 'package:qpay/models/pageable_model.dart';
import 'package:qpay/screens/users/models/managed_user_model.dart';

class UserScreenModel {
  List<ManagedUserModel> users = [];
  bool isLoading = false;
  bool isLoadingMore = false;
  String? errorMessage;
  int currentPage = 0;
  int totalPages = 0;
  int totalElements = 0;
  String searchQuery = '';
  bool selectMode = false;
  Set<String> selectedUserIds = {};

  /// Active filter values (null = not filtered)
  String? filterEmail;
  String? filterPhone;
}

class UserController extends ChangeNotifier {
  final UserScreenModel model = UserScreenModel();
  final Http http = Http();
  BuildContext? context;
  bool _disposed = false;

  UserController(this.context);

  /// Creates a controller without a [BuildContext] — useful when a
  /// bottom sheet or dialog needs to drive API calls through the
  /// controller without participating in the widget tree.
  UserController.forSheet() : context = null;

  @override
  void dispose() {
    _disposed = true;
    super.dispose();
  }

  dynamic _unwrap(dynamic response) {
    if (response is Map && response.containsKey('body')) {
      return response['body'];
    }
    return response;
  }

  String buildQueryParameters(Map<String, String?> params) {
    final filtered = <String, String>{};
    params.forEach((key, value) {
      if (value != null && value.isNotEmpty) {
        filtered[key] = value;
      }
    });
    if (filtered.isEmpty) return '';
    return filtered.entries.map((e) => '${e.key}=${e.value}').join('&');
  }

  // ────────────────────────────────────────────────────────────────
  // 1. LIST USERS  (GET /api/users?username=…&email=…&phone=…)
  // ────────────────────────────────────────────────────────────────
  Future<ApiResponse<PageableModel>> listUsers({
    int page = 0,
    int size = 20,
    String? username,
    String? email,
    String? phone,
  }) async {
    if (page == 0) {
      model.isLoading = true;
      model.users = [];
      model.currentPage = 0;
    } else {
      model.isLoadingMore = true;
    }
    if (!_disposed) notifyListeners();

    try {
      final params = <String, String?>{
        'page': page.toString(),
        'size': size.toString(),
        'username': username,
        'email': email,
        'phone': phone,
      };

      final raw = await http.get('/users?${buildQueryParameters(params)}');
      final response = _unwrap(raw);
      final pageableModel = PageableModel.fromJson(
        response as Map<String, dynamic>,
      );

      final newUsers = pageableModel.content
          .map((e) => ManagedUserModel.fromJson(e as Map<String, dynamic>))
          .toList();

      if (page == 0) {
        model.users = newUsers;
      } else {
        model.users.addAll(newUsers);
      }
      model.currentPage = pageableModel.number;
      model.totalPages = pageableModel.totalPages;
      model.totalElements = pageableModel.totalElements;
      model.isLoading = false;
      model.isLoadingMore = false;

      if (!_disposed) notifyListeners();
      return ApiResponse.success(pageableModel);
    } catch (e) {
      logger.e(e);
      model.errorMessage = e.toString();
      if (page == 0) {
        model.users = [];
      }
      model.isLoading = false;
      model.isLoadingMore = false;
      if (!_disposed) notifyListeners();
      return ApiResponse.failure('Failed to load users');
    }
  }

  // ────────────────────────────────────────────────────────────────
  // 2. LIST WORKSPACE USERS  (GET /api/users/workspace?workspaceId=…)
  // ────────────────────────────────────────────────────────────────
  Future<ApiResponse<PageableModel>> listWorkspaceUsers({
    required String workspaceId,
    int page = 0,
    int size = 20,
    String? username,
    String? email,
    String? phone,
  }) async {
    if (page == 0) {
      model.isLoading = true;
      model.users = [];
      model.currentPage = 0;
    } else {
      model.isLoadingMore = true;
    }
    if (!_disposed) notifyListeners();

    try {
      final params = <String, String?>{
        'workspaceId': workspaceId,
        'page': page.toString(),
        'size': size.toString(),
        'username': username,
        'email': email,
        'phone': phone,
      };

      final raw = await http.get(
        '/users/workspace?${buildQueryParameters(params)}',
      );
      final response = _unwrap(raw);
      final pageableModel = PageableModel.fromJson(
        response as Map<String, dynamic>,
      );

      final newUsers = pageableModel.content
          .map((e) => ManagedUserModel.fromJson(e as Map<String, dynamic>))
          .toList();

      if (page == 0) {
        model.users = newUsers;
      } else {
        model.users.addAll(newUsers);
      }
      model.currentPage = pageableModel.number;
      model.totalPages = pageableModel.totalPages;
      model.totalElements = pageableModel.totalElements;
      model.isLoading = false;
      model.isLoadingMore = false;

      if (!_disposed) notifyListeners();
      return ApiResponse.success(pageableModel);
    } catch (e) {
      logger.e(e);
      model.errorMessage = e.toString();
      if (page == 0) {
        model.users = [];
      }
      model.isLoading = false;
      model.isLoadingMore = false;
      if (!_disposed) notifyListeners();
      return ApiResponse.failure('Failed to load workspace users');
    }
  }

  // ────────────────────────────────────────────────────────────────
  // 3. ASSOCIATE USER TO WORKSPACE
  //    POST /api/workspaces/{workspaceId}/users/{userId}
  // ────────────────────────────────────────────────────────────────
  Future<ApiResponse<void>> associateUser({
    required String workspaceId,
    required String userId,
  }) async {
    try {
      await http.postRaw(
        '/workspaces/$workspaceId/users/$userId',
      );
      // Refresh the list after association so the UI stays in sync
      await listWorkspaceUsers(workspaceId: workspaceId, page: 0);
      return ApiResponse.success(null);
    } catch (e) {
      logger.e(e);
      model.errorMessage = e.toString();
      if (!_disposed) notifyListeners();
      return ApiResponse.failure('Failed to associate user to workspace');
    }
  }

  // ────────────────────────────────────────────────────────────────
  // 4. DISSOCIATE USER FROM WORKSPACE
  //    DELETE /api/workspaces/{workspaceId}/users/{userId}
  // ────────────────────────────────────────────────────────────────
  Future<ApiResponse<void>> dissociateUser({
    required String workspaceId,
    required String userId,
  }) async {
    try {
      await http.delete('/workspaces/$workspaceId/users/$userId');
      // Refresh the workspace users list after dissociation
      await listWorkspaceUsers(workspaceId: workspaceId, page: 0);
      return ApiResponse.success(null);
    } catch (e) {
      logger.e(e);
      model.errorMessage = e.toString();
      if (!_disposed) notifyListeners();
      return ApiResponse.failure('Failed to dissociate user from workspace');
    }
  }

  // ────────────────────────────────────────────────────────────────
  // Convenience helpers
  // ────────────────────────────────────────────────────────────────

  Future<void> searchUsers({required String workspaceId, String? name}) async {
    model.searchQuery = name ?? '';
    await listWorkspaceUsers(
      workspaceId: workspaceId,
      page: 0,
      username: name,
      email: model.filterEmail,
      phone: model.filterPhone,
    );
  }

  Future<void> applyFilters({
    required String workspaceId,
    String? email,
    String? phone,
  }) async {
    model.filterEmail = email;
    model.filterPhone = phone;
    await listWorkspaceUsers(
      workspaceId: workspaceId,
      page: 0,
      username: model.searchQuery.isNotEmpty ? model.searchQuery : null,
      email: email,
      phone: phone,
    );
  }

  void clearFilters({required String workspaceId}) {
    model.filterEmail = null;
    model.filterPhone = null;
    if (!_disposed) notifyListeners();
    listWorkspaceUsers(
      workspaceId: workspaceId,
      page: 0,
      username: model.searchQuery.isNotEmpty ? model.searchQuery : null,
    );
  }

  Future<void> loadNextPage({required String workspaceId}) async {
    if (model.isLoadingMore || model.currentPage + 1 >= model.totalPages) {
      return;
    }
    await listWorkspaceUsers(
      workspaceId: workspaceId,
      page: model.currentPage + 1,
      username: model.searchQuery.isNotEmpty ? model.searchQuery : null,
      email: model.filterEmail,
      phone: model.filterPhone,
    );
  }

  // ────────────────────────────────────────────────────────────────
  //  Selection helpers for bulk actions
  // ────────────────────────────────────────────────────────────────

  void toggleSelectMode() {
    model.selectMode = !model.selectMode;
    if (!model.selectMode) {
      model.selectedUserIds.clear();
    }
    if (!_disposed) notifyListeners();
  }

  void toggleUserSelection(String userId) {
    if (model.selectedUserIds.contains(userId)) {
      model.selectedUserIds.remove(userId);
    } else {
      model.selectedUserIds.add(userId);
    }
    if (!_disposed) notifyListeners();
  }

  Future<void> dissociateSelectedUsers({
    required String workspaceId,
  }) async {
    final idsToProcess = List<String>.from(model.selectedUserIds);
    model.selectMode = false;
    model.selectedUserIds.clear();
    if (!_disposed) notifyListeners();

    for (final id in idsToProcess) {
      await dissociateUser(workspaceId: workspaceId, userId: id);
    }
  }
}