import 'package:dartz/dartz.dart';

import '../../../../core/errors/failures.dart';
import '../../data/models/login_request_model.dart';
import '../entities/user_entity.dart';
import '../repositories/auth_repository.dart';

/// Use case for user login
///
/// Encapsulates the business logic for authentication
/// Validates input, calls repository, and handles the response
class LoginUseCase {
  final AuthRepository repository;

  LoginUseCase(this.repository);

  /// Execute login operation
  ///
  /// [request] - Login credentials (username and password)
  ///
  /// Returns [Right(UserEntity)] on successful login
  /// Returns [Left(Failure)] on error:
  /// - [ValidationFailure] if credentials are invalid
  /// - [AuthenticationFailure] if login fails
  /// - [NetworkFailure] if network error occurs
  Future<Either<Failure, UserEntity>> call(LoginRequestModel request) async {
    // Validate input
    final validationError = _validateInput(request);
    if (validationError != null) {
      return Left(validationError);
    }

    // Call repository to perform login
    return await repository.login(request);
  }

  /// Validate login request input
  ///
  /// Returns [ValidationFailure] if validation fails, null otherwise
  ValidationFailure? _validateInput(LoginRequestModel request) {
    // Validate username
    if (request.username.trim().isEmpty) {
      return const ValidationFailure('Username is required');
    }

    if (request.username.length < 3) {
      return const ValidationFailure('Username must be at least 3 characters');
    }

    // Validate password
    if (request.password.isEmpty) {
      return const ValidationFailure('Password is required');
    }

    if (request.password.length < 6) {
      return const ValidationFailure('Password must be at least 6 characters');
    }

    return null;
  }
}

/// Use case for user logout
class LogoutUseCase {
  final AuthRepository repository;

  LogoutUseCase(this.repository);

  /// Execute logout operation
  ///
  /// Returns [Right(void)] on successful logout
  /// Returns [Left(Failure)] on error
  Future<Either<Failure, void>> call() async {
    return await repository.logout();
  }
}

/// Use case for checking authentication status
class CheckAuthStatusUseCase {
  final AuthRepository repository;

  CheckAuthStatusUseCase(this.repository);

  /// Check if user is authenticated
  ///
  /// Returns true if user has valid access token
  Future<bool> call() async {
    return await repository.isAuthenticated();
  }
}

/// Use case for getting current user
class GetCurrentUserUseCase {
  final AuthRepository repository;

  GetCurrentUserUseCase(this.repository);

  /// Get current authenticated user
  ///
  /// Returns [Right(UserEntity)] if user is authenticated
  /// Returns [Left(Failure)] if no user found or error occurs
  Future<Either<Failure, UserEntity>> call() async {
    return await repository.getCurrentUser();
  }
}

/// Use case for refreshing access token
class RefreshTokenUseCase {
  final AuthRepository repository;

  RefreshTokenUseCase(this.repository);

  /// Refresh access token using refresh token
  ///
  /// [refreshToken] - The refresh token
  ///
  /// Returns [Right(UserEntity)] with new tokens on success
  /// Returns [Left(Failure)] on error
  Future<Either<Failure, UserEntity>> call(String refreshToken) async {
    if (refreshToken.isEmpty) {
      return const Left(ValidationFailure('Refresh token is required'));
    }

    return await repository.refreshToken(refreshToken);
  }
}
