import Foundation
import FluentSQLiteDriver
import Crypto

private extension FieldProperty {
    convenience init(_ key: PasswordReset.Key) {
        self.init(key: key.key)
    }
}

private extension ParentProperty {
    convenience init(_ key: PasswordReset.Key) {
        self.init(key: key.key)
    }
}

extension PasswordReset.Key {
    var key: FieldKey {
        .init(stringLiteral: rawValue)
    }
}

final class PasswordReset: Model {

    /// The name of the SQLite table
    static let schema = "reset"

    enum Key: String {
        case id = "id"
        case user = "user"
        case token = "token"
        case expiry = "expiry"
    }

    /// The unique identifier for the reset request
    @ID(key: .id)
    var id: UUID?

    /// The user associated with the reset request
    @Parent(.user)
    var user: User

    /// The random reset token issued with the email
    @Field(.token)
    var resetToken: String

    /// The time when the reset token expires and can't be used anymore
    @Field(.expiry)
    var expiryDate: Date

    init() {
        self.resetToken = .newToken()
        self.expiryDate = Self.currentExpiryDate()
    }

    func renew() {
        self.resetToken = .newToken()
        self.expiryDate = Self.currentExpiryDate()
    }

    /// Creates a new password reset.
    init(id: UUID? = nil, user: User) {
        self.id = id
        self.$user.id = user.id!
        self.resetToken = .newToken()
        self.expiryDate = Self.currentExpiryDate()
    }

    private static func currentExpiryDate() -> Date {
        Date().addingTimeInterval(15*60)
    }
}
