package com.vaessl.app.connection;

import java.time.Instant;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.vaessl.app.exception.WrongServiceTypeException;
import com.vaessl.app.shared.ServiceType;

@Service
public class ConnectionService {

    private final Map<ServiceType, ConnectionProvider> providerRegistry;

    private final ConnectionRepository cRepository;

    public ConnectionService(List<ConnectionProvider> providers, ConnectionRepository cRepository) {
        Map<ServiceType, ConnectionProvider> registry = new EnumMap<>(ServiceType.class);
        for (ConnectionProvider provider : providers) {
            registry.put(provider.getServiceType(), provider);
        }
        this.providerRegistry = registry;
        this.cRepository = cRepository;
    }

    public LoginResult login(ConnectionRequest request) {

        ConnectionProvider provider = providerRegistry.get(request.serviceType());

        if (provider == null) {
            throw new WrongServiceTypeException();
        }

        provider.checkCredentials(request);

        ConnectionResponse response = provider.authenticate(request);

        ConnectionEntity existing = provider.findUniqueConnectionEntry(request);

        ConnectionEntity saved;
        if (existing != null) {
            provider.updateToRepository(existing, response);
            saved = existing;
        } else {
            ConnectionEntity newEntity = provider.connectionToEntity(request, response);
            saved = cRepository.save(newEntity);
        }

        return new LoginResult(saved.getId(), response.expiresAt());
    }

    public ConnectionStatusResponse getConnectionStatus(ServiceType serviceType,
            Long connectionId) {
        ConnectionEntity entity = cRepository.findById(connectionId).orElse(null);
        if (entity == null)
            return null;

        ConnectionProvider provider = providerRegistry.get(serviceType);
        Instant expiresAt = (provider != null) ? provider.getTokenExpiry(entity) : null;
        boolean connected = expiresAt == null || expiresAt.isAfter(Instant.now());

        return new ConnectionStatusResponse(serviceType.name(), entity.getAppUrl(),
                entity.getUsername(), expiresAt, connected);
    }
}
