import Foundation

/// Result enum representing outcomes of authentication operations.
enum AuthResult<T> {
    case success(T)
    case failure(AuthError)
}

/// Errors that can occur during authentication operations.
enum AuthError: Error, LocalizedError, Equatable {
    case invalidInput(String)
    case userAlreadyExists
    case invalidCredentials
    case userNotFound
    case incorrectPassword
    case storageError
    case networkError(String)

    var errorDescription: String? {
        switch self {
        case .invalidInput(let reason):
            return reason
        case .userAlreadyExists:
            return "账号已存在，请直接登录"
        case .invalidCredentials:
            return "账号或密码错误"
        case .userNotFound:
            return "未找到对应账号"
        case .incorrectPassword:
            return "原密码校验错误"
        case .storageError:
            return "本地存储操作异常"
        case .networkError(let msg):
            return "网络连接失败: \(msg)"
        }
    }
}

/// Login request transfer object.
struct LoginRequest {
    let identifier: String
    let password: String
}

/// Registration request transfer object.
struct RegisterRequest {
    let username: String
    let identifier: String
    let password: String
}

/// Profile update transfer object.
struct UpdateProfileRequest {
    let username: String?
    let email: String?
    let phoneNumber: String?
    let avatarURL: String?
}

/// Password modification transfer object.
struct ChangePasswordRequest {
    let oldPassword: String
    let newPassword: String
}

/// Abstract contract for authentication service implementations.
/// Allows swapping between local persistence and remote server HTTP API seamlessly.
protocol AuthServiceProtocol {
    func restoreSession(completion: @escaping (AuthResult<UserAccount?>) -> Void)
    func login(request: LoginRequest, completion: @escaping (AuthResult<UserAccount>) -> Void)
    func register(request: RegisterRequest, completion: @escaping (AuthResult<UserAccount>) -> Void)
    func updateProfile(request: UpdateProfileRequest, completion: @escaping (AuthResult<UserAccount>) -> Void)
    func changePassword(request: ChangePasswordRequest, completion: @escaping (AuthResult<Bool>) -> Void)
    func logout(completion: @escaping () -> Void)
    func getCurrentUser() -> UserAccount?
}
