import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:real_estate_mobile/core/constants/api_constants.dart';
import 'package:real_estate_mobile/core/network/api_client.dart';
import 'package:real_estate_mobile/core/network/api_exceptions.dart';
import 'package:real_estate_mobile/features/agents/data/models/agent_profile.dart';
import 'package:real_estate_mobile/features/agents/data/models/agent_type.dart';
import 'package:real_estate_mobile/features/agents/data/models/filterable_field.dart';

class SearchAgentsResponse {
  final List<AgentProfile> data;
  final int total;
  final int page;
  final int limit;
  final int totalPages;

  const SearchAgentsResponse({
    required this.data,
    required this.total,
    required this.page,
    required this.limit,
    required this.totalPages,
  });

  /// Parses: { data: [...], meta: { total, page, limit, totalPages } }
  factory SearchAgentsResponse.fromJson(Map<String, dynamic> json) {
    final meta = json['meta'] as Map<String, dynamic>? ?? {};
    return SearchAgentsResponse(
      data: (json['data'] as List<dynamic>?)
              ?.map(
                  (e) => AgentProfile.fromJson(e as Map<String, dynamic>))
              .toList() ??
          [],
      total: meta['total'] as int? ?? 0,
      page: meta['page'] as int? ?? 1,
      limit: meta['limit'] as int? ?? 10,
      totalPages: meta['totalPages'] as int? ?? 1,
    );
  }
}

class AgentsRepository {
  final Dio _dio = ApiClient.instance.dio;

  /// Search agents: GET /agents
  /// Response: { success, data: { data: [...], meta: {...} } }
  Future<SearchAgentsResponse> searchAgents({
    String? agentTypeId,
    String? search,
    int page = 1,
    int limit = 10,
    String? sortBy,
    String? sortOrder,
    Map<String, List<String>>? filters,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'page': page,
        'limit': limit,
      };

      if (agentTypeId != null) queryParams['agentTypeId'] = agentTypeId;
      if (search != null && search.isNotEmpty) queryParams['search'] = search;
      if (sortBy != null) queryParams['sortBy'] = sortBy;
      if (sortOrder != null) queryParams['sortOrder'] = sortOrder;
      if (filters != null && filters.isNotEmpty) {
        queryParams['filters'] = jsonEncode(filters);
      }

      final response = await _dio.get(
        ApiConstants.agents,
        queryParameters: queryParams,
      );

      // Backend wraps: { success: true, data: { data: [...], meta: {...} } }
      final responseData = response.data;
      final payload = responseData['data'] as Map<String, dynamic>;
      return SearchAgentsResponse.fromJson(payload);
    } on DioException catch (e) {
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException(
        message: e.message ?? 'Failed to fetch agents',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Get filterable profile fields: GET /profile-fields/filterable
  /// Response: { success, data: [...] }
  Future<List<FilterableField>> getFilterableFields() async {
    try {
      final response = await _dio.get(ApiConstants.filterableFields);
      final data = response.data['data'] as List<dynamic>;
      return data
          .map((e) => FilterableField.fromJson(e as Map<String, dynamic>))
          .toList();
    } on DioException catch (e) {
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException(
        message: e.message ?? 'Failed to fetch filterable fields',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Get agent by ID: GET /agents/{id}
  /// Response: { success, data: AgentProfile }
  Future<AgentProfile> getAgentById(String id) async {
    try {
      final response = await _dio.get('${ApiConstants.agents}/$id');
      final data = response.data['data'] as Map<String, dynamic>;
      return AgentProfile.fromJson(data);
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to fetch agent',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Get field values for agent: GET /agents/{id}/field-values
  /// Response: { success, data: { agentProfileId, fieldValues: [...] } }
  Future<List<AgentFieldValue>> getFieldValues(String agentId) async {
    try {
      final response =
          await _dio.get('${ApiConstants.agents}/$agentId/field-values');
      final data = response.data['data'] as Map<String, dynamic>;
      final fieldValues = data['fieldValues'] as List<dynamic>? ?? [];
      return fieldValues
          .map((e) => AgentFieldValue.fromFieldValueResponse(
              e as Map<String, dynamic>))
          .toList();
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException(
        message: e.message ?? 'Failed to fetch field values',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// Get testimonials for agent: GET /testimonials/agent/{agentProfileId}
  Future<List<Map<String, dynamic>>> getTestimonials(String agentId,
      {int limit = 10}) async {
    try {
      final response = await _dio.get(
        '${ApiConstants.testimonials}/agent/$agentId',
        queryParameters: {'limit': limit},
      );
      final data = response.data['data'] as List<dynamic>? ?? [];
      return data.cast<Map<String, dynamic>>();
    } on DioException catch (_) {
      return [];
    }
  }

  /// Get connection status: GET /connection-requests/status/{agentProfileId}
  Future<Map<String, dynamic>?> getConnectionStatus(String agentId) async {
    try {
      final response = await _dio
          .get('${ApiConstants.connectionRequests}/status/$agentId');
      return response.data['data'] as Map<String, dynamic>?;
    } on DioException catch (_) {
      return null;
    }
  }

  /// Create connection request: POST /connection-requests
  Future<bool> createConnectionRequest(String agentId,
      {String? message}) async {
    try {
      await _dio.post(ApiConstants.connectionRequests, data: {
        'agentProfileId': agentId,
        if (message != null && message.isNotEmpty) 'message': message,
      });
      return true;
    } on DioException catch (_) {
      return false;
    }
  }

  /// Cancel connection request: DELETE /connection-requests/{requestId}
  Future<bool> cancelConnectionRequest(String requestId) async {
    try {
      await _dio.delete('${ApiConstants.connectionRequests}/$requestId');
      return true;
    } on DioException catch (_) {
      return false;
    }
  }

  /// Get received connection requests: GET /connection-requests/received?status=...
  Future<List<Map<String, dynamic>>> getReceivedRequests(String status) async {
    try {
      final response = await _dio.get(
        '${ApiConstants.connectionRequests}/received',
        queryParameters: {'status': status},
      );
      final data = response.data['data'] as List<dynamic>? ?? [];
      return data.cast<Map<String, dynamic>>();
    } on DioException catch (_) {
      return [];
    }
  }

  /// Respond to connection request: PATCH /connection-requests/{id}/respond
  Future<bool> respondToRequest(String requestId, String status) async {
    try {
      await _dio.patch(
        '${ApiConstants.connectionRequests}/$requestId/respond',
        data: {'status': status},
      );
      return true;
    } on DioException catch (_) {
      return false;
    }
  }

  /// Get agent types: GET /agent-types
  /// Response: { success, data: [...] }
  Future<List<AgentType>> getAgentTypes() async {
    try {
      final response = await _dio.get(ApiConstants.agentTypes);

      // Backend wraps: { success: true, data: [...] }
      final data = response.data['data'] as List<dynamic>;
      return data
          .map((e) => AgentType.fromJson(e as Map<String, dynamic>))
          .toList();
    } on DioException catch (e) {
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException(
        message: e.message ?? 'Failed to fetch agent types',
        statusCode: e.response?.statusCode,
      );
    }
  }
}
