import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../core/constants/app_constants.dart';
import '../../core/errors/failures.dart';
import '../../core/errors/exceptions.dart';
import '../../domain/repositories/user_repository.dart';
import '../../models/user_model.dart';
import '../datasources/remote/user_remote_datasource.dart';
import '../models/common/paginated_response.dart';
import '../models/user/user_dto.dart';

/// 사용자 관리 Repository 구현체 (서버 API v0.2.1 대응)
/// Clean Architecture Data Layer - Repository 구현
/// 도메인 레이어와 데이터 소스 사이의 변환 및 에러 처리 담당
@Injectable(as: UserRepository)
class UserRepositoryImpl implements UserRepository {
  final UserRemoteDataSource _remoteDataSource;

  UserRepositoryImpl(this._remoteDataSource);

  /// 사용자 목록 조회 (페이지네이션 지원)
  @override
  Future<Either<Failure, PaginatedResponse<User>>> getUsers({
    int? page,
    int? perPage,
    UserRole? role,
    bool? isActive,
  }) async {
    try {
      final result = await _remoteDataSource.getUsers(
        page: page ?? 1,
        perPage: perPage ?? AppConstants.userPageSize,
        isActive: isActive,
        role: role?.name, // UserRole enum을 문자열로 변환
      );
      
      // UserListResponse를 PaginatedResponse<User>로 변환
      final users = result.items.map((dto) => dto.toDomainModel()).toList();
      
      final paginatedResult = PaginatedResponse<User>(
        items: users,
        page: result.currentPage,
        size: result.pageSize ?? 20,
        totalElements: result.totalCount,
        totalPages: result.totalPages,
        first: result.currentPage == 1, // 첫 페이지 여부
        last: result.currentPage >= result.totalPages, // 마지막 페이지 여부
      );
      
      return Right(paginatedResult);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e));
    } catch (e) {
      return Left(ServerFailure(
        message: '사용자 목록 조회 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// 단일 사용자 조회
  @override
  Future<Either<Failure, User>> getUserById(int id) async {
    try {
      final dto = await _remoteDataSource.getUser(id);
      final user = dto.toDomainModel();
      return Right(user);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e, resourceId: id.toString()));
    } catch (e) {
      return Left(ServerFailure(
        message: '사용자 정보 조회 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// 사용자 계정 생성
  @override
  Future<Either<Failure, User>> createUser({
    required String name,
    String? email,
    String? phone,
    required int companiesId,
  }) async {
    try {
      final request = UserRequestDto(
        name: name,
        email: email,
        phone: phone,
        companiesId: companiesId,
      );
      
      final dto = await _remoteDataSource.createUser(request);
      final user = dto.toDomainModel();
      return Right(user);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e));
    } catch (e) {
      return Left(ServerFailure(
        message: '사용자 생성 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// 사용자 정보 수정
  @override
  Future<Either<Failure, User>> updateUser(int id, User user, {String? newPassword}) async {
    try {
      final request = UserUpdateRequestDto.fromDomain(user, newPassword: newPassword);
      
      final dto = await _remoteDataSource.updateUser(id, request);
      final updatedUser = dto.toDomainModel();
      return Right(updatedUser);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e, resourceId: id.toString()));
    } catch (e) {
      return Left(ServerFailure(
        message: '사용자 정보 수정 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// 사용자 소프트 삭제
  @override
  Future<Either<Failure, void>> deleteUser(int id) async {
    try {
      await _remoteDataSource.deleteUser(id);
      return const Right(null);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e, resourceId: id.toString()));
    } catch (e) {
      return Left(ServerFailure(
        message: '사용자 삭제 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// 사용자명 중복 확인 (UI 호환용)
  @override
  Future<Either<Failure, bool>> checkUsernameAvailability(String name) async {
    // 백엔드에서 지원하지 않으므로 항상 true 반환
    return const Right(true);
  }

  /// ApiException을 적절한 Failure로 매핑하는 헬퍼 메서드
  Failure _mapApiExceptionToFailure(ApiException exception, {String? resourceId}) {
    final statusCode = exception.statusCode;
    final message = exception.message;
    
    if (statusCode == 404) {
      return NotFoundFailure(
        message: '요청한 사용자를 찾을 수 없습니다.',
        resourceType: 'User',
        resourceId: resourceId,
      );
    } else if (statusCode == 400) {
      if (message.contains('duplicate') || message.contains('중복')) {
        return DuplicateFailure(
          message: '이미 사용 중인 사용자명 또는 이메일입니다.',
          field: 'username',
          value: '',
        );
      } else {
        return ValidationFailure(message: message);
      }
    } else if (statusCode == 401) {
      return AuthenticationFailure(message: '인증이 필요합니다.');
    } else if (statusCode == 403) {
      return AuthorizationFailure(message: '권한이 없습니다.');
    } else {
      return ServerFailure(message: message);
    }
  }
}
