import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:superport/core/errors/exceptions.dart';
import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/data/models/user/user_dto.dart';

/// 사용자 원격 데이터 소스 (서버 API v0.2.1 대응)
/// 엔드포인트: /api/v1/users
abstract class UserRemoteDataSource {
  /// 사용자 목록 조회 (페이지네이션 지원)
  Future<UserListDto> getUsers({
    int page = 1,
    int perPage = 20,
    bool? isActive,
    String? role,
  });
  
  /// 단일 사용자 조회
  Future<UserDto> getUser(int id);
  
  /// 사용자 생성
  Future<UserDto> createUser(CreateUserRequest request);
  
  /// 사용자 정보 수정 (비밀번호 포함)
  Future<UserDto> updateUser(int id, UpdateUserRequest request);
  
  /// 사용자 소프트 삭제 (is_active = false)
  Future<void> deleteUser(int id);
  
  /// 사용자명 중복 확인
  Future<CheckUsernameResponse> checkUsernameAvailability(String username);
}

@LazySingleton(as: UserRemoteDataSource)
class UserRemoteDataSourceImpl implements UserRemoteDataSource {
  final ApiClient _apiClient;

  UserRemoteDataSourceImpl(this._apiClient);

  /// 사용자 목록 조회 (서버 API v0.2.1 대응)
  @override
  Future<UserListDto> getUsers({
    int page = 1,
    int perPage = 20,
    bool? isActive,
    String? role,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'page': page,
        'per_page': perPage,
      };
      
      // 필터 파라미터 추가 (서버에서 지원하는 것만)
      if (isActive != null) {
        queryParams['is_active'] = isActive;
      }
      if (role != null) {
        queryParams['role'] = role;
      }

      final response = await _apiClient.get(
        '/users',
        queryParameters: queryParams,
      );

      // 백엔드 API v0.2.1 실제 응답 형식 처리 (success: true)
      if (response.data != null && 
          response.data['success'] == true && 
          response.data['data'] != null) {
        
        final data = response.data['data'];
        final paginationData = response.data['pagination'];
        
        // 배열 응답 + 페이지네이션 정보
        if (data is List && paginationData is Map) {
          return UserListDto(
            users: data.map((json) => UserDto.fromJson(json)).toList(),
            total: paginationData['total'] ?? data.length,
            page: paginationData['page'] ?? page,
            perPage: paginationData['per_page'] ?? perPage,
            totalPages: paginationData['total_pages'] ?? 1,
          );
        } 
        // 기존 구조 호환성 유지
        else if (data is Map && data['users'] != null) {
          return UserListDto.fromJson(Map<String, dynamic>.from(data));
        } 
        // 단순 배열 응답인 경우
        else if (data is List) {
          return UserListDto(
            users: data.map((json) => UserDto.fromJson(json)).toList(),
            total: data.length,
            page: page,
            perPage: perPage,
            totalPages: 1,
          );
        } 
        else {
          throw ApiException(
            message: 'Unexpected response format for user list',
            statusCode: response.statusCode,
          );
        }
      } else {
        throw ApiException(
          message: response.data?['message'] ?? '사용자 목록을 불러오는데 실패했습니다',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      throw ApiException(
        message: e.response?.data?['message'] ?? 
                 e.message ?? 
                 '사용자 목록을 불러오는데 실패했습니다',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// 단일 사용자 조회 (GET /api/v1/users/{id})
  @override
  Future<UserDto> getUser(int id) async {
    try {
      final response = await _apiClient.get('/users/$id');
      
      if (response.data != null && 
          response.data['success'] == true && 
          response.data['data'] != null) {
        return UserDto.fromJson(response.data['data']);
      } else {
        throw ApiException(
          message: response.data?['message'] ?? '사용자 정보를 불러오는데 실패했습니다',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      throw ApiException(
        message: e.response?.data?['message'] ?? 
                 e.message ?? 
                 '사용자 정보를 불러오는데 실패했습니다',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// 사용자 생성 (POST /api/v1/users)
  @override
  Future<UserDto> createUser(CreateUserRequest request) async {
    try {
      final response = await _apiClient.post(
        '/users',
        data: request.toJson(),
      );

      if (response.data != null && 
          response.data['success'] == true && 
          response.data['data'] != null) {
        return UserDto.fromJson(response.data['data']);
      } else {
        throw ApiException(
          message: response.data?['message'] ?? '사용자 생성에 실패했습니다',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      throw ApiException(
        message: e.response?.data?['message'] ?? 
                 e.message ?? 
                 '사용자 생성에 실패했습니다',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// 사용자 수정 (PUT /api/v1/users/{id})
  @override
  Future<UserDto> updateUser(int id, UpdateUserRequest request) async {
    try {
      // null이나 빈 값 필터링하여 실제로 변경된 필드만 전송
      final requestData = request.toJson();
      requestData.removeWhere((key, value) => value == null || 
                                              (value is String && value.isEmpty));
      
      final response = await _apiClient.put(
        '/users/$id',
        data: requestData,
      );

      if (response.data != null && 
          response.data['success'] == true && 
          response.data['data'] != null) {
        return UserDto.fromJson(response.data['data']);
      } else {
        throw ApiException(
          message: response.data?['message'] ?? '사용자 정보 수정에 실패했습니다',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      throw ApiException(
        message: e.response?.data?['message'] ?? 
                 e.message ?? 
                 '사용자 정보 수정에 실패했습니다',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// 사용자 소프트 삭제 (DELETE /api/v1/users/{id})
  /// 서버에서 is_active = false로 설정
  @override
  Future<void> deleteUser(int id) async {
    try {
      final response = await _apiClient.delete('/users/$id');
      
      // 소프트 딜리트는 응답 데이터가 있을 수 있음
      if (response.statusCode != null && response.statusCode! >= 400) {
        throw ApiException(
          message: response.data?['message'] ?? '사용자 삭제에 실패했습니다',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      throw ApiException(
        message: e.response?.data?['message'] ?? 
                 e.message ?? 
                 '사용자 삭제에 실패했습니다',
        statusCode: e.response?.statusCode,
      );
    }
  }

  /// 사용자명 중복 확인 (구현 예정 - 현재 서버에서 미지원)
  /// TODO: 서버 API에 해당 엔드포인트 추가되면 구현
  @override
  Future<CheckUsernameResponse> checkUsernameAvailability(String username) async {
    try {
      // 임시로 POST 시도를 통한 중복 체크
      // 실제 서버에 해당 엔드포인트가 없다면 항상 available = true 반환
      return const CheckUsernameResponse(
        available: true,
        message: 'Username availability check not implemented in server',
      );
    } catch (e) {
      return const CheckUsernameResponse(
        available: false,
        message: 'Username availability check failed',
      );
    }
  }
}