package gaf3.core.services.auth.service

import com.alibaba.fastjson.JSON
import gaf3.core.exception.BusinessError
import gaf3.core.services.auth.GafAuthConfigure
import gaf3.core.services.auth.domain.AuthToken
import gaf3.core.services.auth.domain.LoginForm
import gaf3.core.services.bff.service.BffUserRoleService
import gaf3.core.services.role.entity.GafRoleItem
import gaf3.core.services.user.domain.UserInfo
import gaf3.core.services.user.service.UserService
import gaf3.core.util.JsonCertToken
import io.jsonwebtoken.Jwts
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers
import org.bouncycastle.cert.X509CertificateHolder
import org.bouncycastle.crypto.Signer
import org.bouncycastle.crypto.digests.SHA1Digest
import org.bouncycastle.crypto.params.AsymmetricKeyParameter
import org.bouncycastle.crypto.signers.RSADigestSigner
import org.bouncycastle.crypto.util.PublicKeyFactory
import org.bouncycastle.util.encoders.Base64
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
import org.springframework.validation.annotation.Validated
import java.io.IOException
import java.security.Key
import java.time.Instant
import java.util.*
import java.util.regex.Pattern
import javax.validation.Valid


@Service
@Validated
class GafAuthService (@Qualifier("jwtSigningKey")val jwtSigningKey: Key, val config: GafAuthConfigure, val userService: UserService, val roleService: BffUserRoleService) {

    fun login(@Valid form: LoginForm): AuthToken {
        val user = if(form.username == "@cert")
            loginByCert(form.password!!)
        else
            userService.login(form.username!!, form.password!!)

        // TODO: 查询用户角色
        var roles: Array<String>? = if(user.account == "admin") {
            arrayOf("superadmin")
        } else {
            roleService.find(GafRoleItem(), user.userId).data?.map {
                p -> (p.code ?: p.id)!!
            }?.toTypedArray()
        }

        // 生成Jwt
        val token = createJwt(subject = form.username!!,
                userId = user.userId!!,
                name = user.name!!,
                roles = roles)
        return AuthToken(user, token, roles)
    }

    fun createJwt(subject: String, userId: String, name: String, roles: Array<String>? = null): String {
        return Jwts.builder()
                .setSubject(subject)
                .setIssuer(config.jwtIssuer ?: "gaf")
                .setExpiration(Date.from(Instant.now().plusSeconds(config.jwtValiditySec)))
                .claim("userId", userId)
                .claim("name", name)
                .claim("roles", roles)
                .signWith(jwtSigningKey)
                .compact()
    }

    /**
     * 证书登录
     */
    fun loginByCert(token: String): UserInfo {
        val jct = JsonCertToken.parse(token)
        // 检查token有效期
        if (System.currentTimeMillis() / 1000 > jct.exp) {
            JsonCertToken.log.debug("Token已过期: {}", Date(jct.exp*1000))
            throw BusinessError(BusinessError.ERR_TOKEN_EXPIRED, "Token验证失败: Token已过期")
        }

        return userService.fetchByAccount(jct.sub)
            ?: throw BusinessError(BusinessError.ERR_USER_NOTEXIST, "用户信息不存在")
    }


    companion object {
        val log: Logger = LoggerFactory.getLogger(GafAuthService::class.java)
    }
}