package com.heaerie.server.auth201.Auth201Server.service;

import com.heaerie.server.auth201.Auth201Server.dto.ClientRegistrationRequest;
import com.heaerie.server.auth201.Auth201Server.dto.ClientRegistrationResponse;
import com.heaerie.server.auth201.Auth201Server.entity.RegisteredClientEntity;
import com.heaerie.server.auth201.Auth201Server.repository.RegisteredClientRepository;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

@Service
public class ClientRegistrationService {

    private final RegisteredClientRepository clientRepository;
    private final PasswordEncoder passwordEncoder;

    public ClientRegistrationService(RegisteredClientRepository clientRepository, 
                                    PasswordEncoder passwordEncoder) {
        this.clientRepository = clientRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Transactional
    public ClientRegistrationResponse registerClient(ClientRegistrationRequest request) {
        // Validate request
        if (request.getClientName() == null || request.getClientName().trim().isEmpty()) {
            throw new IllegalArgumentException("Client name is required");
        }
        
        if (request.getRedirectUris() == null || request.getRedirectUris().isEmpty()) {
            throw new IllegalArgumentException("At least one redirect URI is required");
        }

        // Generate unique client ID
        String clientId;
        do {
            clientId = generateClientId(request.getClientName());
        } while (clientRepository.existsByClientId(clientId));

        // Generate client secret for confidential clients
        String clientSecret = null;
        String encodedSecret = null;
        if ("confidential".equals(request.getClientType())) {
            clientSecret = generateClientSecret();
            encodedSecret = passwordEncoder.encode(clientSecret);
        }

        // Create entity
        RegisteredClientEntity entity = new RegisteredClientEntity();
        entity.setClientId(clientId);
        entity.setClientSecret(encodedSecret);
        entity.setClientName(request.getClientName());
        entity.setClientType(request.getClientType());
        entity.setDescription(request.getDescription());
        entity.setRedirectUris(String.join(",", request.getRedirectUris()));
        
        if (request.getLogoutRedirectUris() != null && !request.getLogoutRedirectUris().isEmpty()) {
            entity.setLogoutRedirectUris(String.join(",", request.getLogoutRedirectUris()));
        }
        
        entity.setGrantTypes(String.join(",", request.getGrantTypes()));
        entity.setScopes(String.join(",", request.getScopes()));
        entity.setRequireConsent(request.isRequireConsent());
        entity.setRequirePkce(request.isRequirePkce());
        entity.setAccessTokenValidity(request.getAccessTokenValidity());
        entity.setRefreshTokenValidity(request.getRefreshTokenValidity());
        entity.setReuseRefreshTokens(request.isReuseRefreshTokens());

        // Save to database
        clientRepository.save(entity);

        // Build response
        ClientRegistrationResponse response = new ClientRegistrationResponse();
        response.setClientId(clientId);
        response.setClientSecret(clientSecret); // Return plain text secret (only shown once)
        response.setClientType(request.getClientType());
        response.setMessage("Client registered successfully");

        return response;
    }

    private String generateClientId(String clientName) {
        String sanitized = clientName.toLowerCase()
                .replaceAll("[^a-z0-9-]", "-")
                .replaceAll("-+", "-")
                .replaceAll("^-|-$", "");
        
        String shortUuid = UUID.randomUUID().toString().substring(0, 8);
        return sanitized + "-" + shortUuid;
    }

    private String generateClientSecret() {
        return UUID.randomUUID().toString().replace("-", "") + 
               UUID.randomUUID().toString().replace("-", "");
    }
}
