package de.votian.services.security;

import de.votian.services.dto.UserSessionDto;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class AuthSessionService {

    private final Map<String, SessionState> authSessions = new ConcurrentHashMap<>();
    private final Map<String, PendingTotpState> pendingTotpSessions = new ConcurrentHashMap<>();

    public String createAuthenticatedSession(UserSessionDto user) {
        String token = UUID.randomUUID().toString();
        authSessions.put(token, new SessionState(user, Instant.now().plus(12, ChronoUnit.HOURS)));
        return token;
    }

    public Optional<UserSessionDto> resolveAuthenticatedSession(String token) {
        if (token == null || token.isBlank()) {
            return Optional.empty();
        }
        SessionState state = authSessions.get(token);
        if (state == null || state.expiresAt().isBefore(Instant.now())) {
            authSessions.remove(token);
            return Optional.empty();
        }
        return Optional.of(state.user());
    }

    public void invalidateAuthenticatedSession(String token) {
        if (token != null) {
            authSessions.remove(token);
        }
    }

    public String createPendingTotpSession(UserSessionDto user) {
        String token = UUID.randomUUID().toString();
        pendingTotpSessions.put(token, new PendingTotpState(user, Instant.now().plus(5, ChronoUnit.MINUTES)));
        return token;
    }

    public Optional<UserSessionDto> consumePendingTotpSession(String token) {
        if (token == null || token.isBlank()) {
            return Optional.empty();
        }
        PendingTotpState state = pendingTotpSessions.remove(token);
        if (state == null || state.expiresAt().isBefore(Instant.now())) {
            return Optional.empty();
        }
        return Optional.of(state.user());
    }

    private record SessionState(UserSessionDto user, Instant expiresAt) { }
    private record PendingTotpState(UserSessionDto user, Instant expiresAt) { }
}
