import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../core/errors/failures.dart';
import '../../core/errors/exceptions.dart';
import '../../domain/repositories/administrator_repository.dart';
import '../datasources/remote/administrator_remote_datasource.dart';
import '../models/administrator_dto.dart';

/// 관리자 관리 Repository 구현체 (백엔드 Administrator 테이블)
/// Clean Architecture Data Layer - Repository 구현
/// 도메인 레이어와 데이터 소스 사이의 변환 및 에러 처리 담당
@Injectable(as: AdministratorRepository)
class AdministratorRepositoryImpl implements AdministratorRepository {
  final AdministratorRemoteDataSource _remoteDataSource;

  AdministratorRepositoryImpl(this._remoteDataSource);

  /// 관리자 목록 조회 (페이지네이션 지원)
  @override
  Future<Either<Failure, AdministratorListResponse>> getAdministrators({
    int? page,
    int? pageSize,
    String? search,
  }) async {
    try {
      final result = await _remoteDataSource.getAdministrators(
        page: page ?? 1,
        pageSize: pageSize ?? 20,
        search: search,
      );
      
      return Right(result);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e));
    } catch (e) {
      return Left(ServerFailure(
        message: '관리자 목록 조회 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

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

  /// 관리자 계정 생성
  @override
  Future<Either<Failure, AdministratorDto>> createAdministrator(
    AdministratorRequestDto administrator,
  ) async {
    try {
      final dto = await _remoteDataSource.createAdministrator(administrator);
      return Right(dto);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e));
    } catch (e) {
      return Left(ServerFailure(
        message: '관리자 계정 생성 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// 관리자 정보 수정
  @override
  Future<Either<Failure, AdministratorDto>> updateAdministrator(
    int id,
    AdministratorUpdateRequestDto administrator,
  ) async {
    try {
      final dto = await _remoteDataSource.updateAdministrator(id, administrator);
      return Right(dto);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e, resourceId: id.toString()));
    } catch (e) {
      return Left(ServerFailure(
        message: '관리자 정보 수정 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

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

  /// 이메일 중복 확인
  @override
  Future<Either<Failure, bool>> isDuplicateEmail(String email, {int? excludeId}) async {
    try {
      final isAvailable = await _remoteDataSource.checkEmailAvailability(
        email,
        excludeId: excludeId,
      );
      // checkEmailAvailability는 사용 가능 여부를 반환하므로
      // 중복 여부는 그 반대값
      return Right(!isAvailable);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e));
    } catch (e) {
      return Left(ServerFailure(
        message: '이메일 중복 확인 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// 관리자 인증 (로그인용)
  @override
  Future<Either<Failure, AdministratorDto>> authenticateAdministrator(
    String email,
    String password,
  ) async {
    try {
      final dto = await _remoteDataSource.authenticateAdministrator(email, password);
      return Right(dto);
    } on ApiException catch (e) {
      return Left(_mapApiExceptionToFailure(e));
    } catch (e) {
      return Left(ServerFailure(
        message: '관리자 인증 중 오류가 발생했습니다: ${e.toString()}',
      ));
    }
  }

  /// API 예외를 Failure로 매핑
  Failure _mapApiExceptionToFailure(ApiException exception, {String? resourceId}) {
    switch (exception.statusCode) {
      case 400:
        return ValidationFailure(
          message: exception.message ?? '잘못된 요청입니다.',
        );
      case 401:
        return AuthFailure(
          message: exception.message ?? '인증이 필요합니다.',
        );
      case 403:
        return AuthFailure(
          message: exception.message ?? '접근 권한이 없습니다.',
        );
      case 404:
        final resourceName = resourceId != null ? '관리자 (ID: $resourceId)' : '요청한 리소스';
        return NotFoundFailure(
          message: exception.message ?? '$resourceName를 찾을 수 없습니다.',
          resourceId: resourceId,
        );
      case 409:
        return DuplicateFailure(
          message: exception.message ?? '중복된 데이터가 존재합니다.',
        );
      case 422:
        return ValidationFailure(
          message: exception.message ?? '입력된 데이터가 유효하지 않습니다.',
        );
      case 500:
      case 502:
      case 503:
      case 504:
        return ServerFailure(
          message: exception.message ?? '서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.',
        );
      default:
        return ServerFailure(
          message: exception.message ?? '알 수 없는 오류가 발생했습니다.',
        );
    }
  }
}