package dev.dinauer.maven.maven.token;

import dev.dinauer.maven.maven.token.dto.TokenCreation;
import dev.dinauer.maven.maven.token.dto.TokenSecret;
import io.quarkus.elytron.security.common.BcryptUtil;
import io.quarkus.security.UnauthorizedException;
import io.vertx.core.http.HttpHeaders;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import io.vertx.core.http.HttpServerRequest;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.core.SecurityContext;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.UUID;

@ApplicationScoped
public class TokenService
{
    @Inject
    TokenRepo tokenRepo;

    @Inject
    HttpServerRequest request;

    @Inject
    SecurityContext securityContext;

    @ConfigProperty(name = "dev.dinauer.maven.auth.enabled")
    Boolean authEnabled;

    public TokenSecret create(TokenCreation tokenCreation)
    {
        String secret = UUID.randomUUID().toString();
        TokenEntity entity = new TokenEntity()
            .setName(tokenCreation.name())
            .setToken(BcryptUtil.bcryptHash(secret))
            .setUserId(securityContext.getUserPrincipal().getName())
            .setExpiresAt(tokenCreation.expiresAt())
            .setCreatedAt(ZonedDateTime.now());
        tokenRepo.persist(entity);
        return new TokenSecret(tokenCreation.name(), tokenCreation.expiresAt(), secret, entity.getCreatedAt());
    }

    public String require()
    {
        if (Boolean.FALSE.equals(authEnabled))
        {
            return null;
        }
        String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (authHeader != null && !authHeader.isBlank())
        {
            String[] sections = authHeader.split("\\s+");
            if (sections.length == 2 && sections[0].equals("Basic"))
            {
                String value = new String(Base64.getDecoder().decode(sections[1]));
                String[] parts = value.split(":");
                if (parts.length == 2)
                {
                    String username = parts[0];
                    String password = parts[1];
                    for (TokenEntity token : tokenRepo.findByUserId(username))
                    {
                        if (BcryptUtil.matches(password, token.getToken()))
                        {
                            LocalDate now = LocalDate.now();
                            if (now.equals(token.getExpiresAt()) || now.isBefore(token.getExpiresAt()))
                            {
                                return username;
                            }
                        }
                    }
                    throw new UnauthorizedException();
                }
            }
            throw new BadRequestException();
        }
        throw new UnauthorizedException();
    }
}
