import DatabaseClient
import Dependencies
import DependenciesMacros
import ManualDCore
import Vapor

extension DependencyValues {
  public var authClient: AuthClient {
    get { self[AuthClient.self] }
    set { self[AuthClient.self] = newValue }
  }
}

@DependencyClient
public struct AuthClient: Sendable {
  public var createAndLogin: @Sendable (User.Create) async throws -> User
  public var currentUser: @Sendable () throws -> User
  public var login: @Sendable (User.Login) async throws -> User
  public var logout: @Sendable () throws -> Void
}

extension AuthClient: TestDependencyKey {
  public static let testValue = Self()

  public static func live(on request: Request) -> Self {
    @Dependency(\.database) var database

    return .init(
      createAndLogin: { createForm in
        let user = try await database.users.create(createForm)
        _ = try await database.users.login(
          .init(email: createForm.email, password: createForm.password)
        )
        request.auth.login(user)
        request.logger.debug("LOGGED IN: \(user.id)")
        return user
      },
      currentUser: {
        try request.auth.require(User.self)
      },
      login: { loginForm in
        let token = try await database.users.login(loginForm)
        let user = try await database.users.get(token.userID)!
        request.session.authenticate(user)
        request.logger.debug("LOGGED IN: \(user.id)")
        return user
      },
      logout: { request.auth.logout(User.self) }
    )
  }
}
