package com.vaessl.app.connection;

import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

import com.vaessl.app.exception.EmptyCredentialsException;
import com.vaessl.app.exception.RemoteApiException;
import com.vaessl.app.shared.ServiceType;
import lombok.RequiredArgsConstructor;
import static com.vaessl.app.shared.Endpoint.*;

@Component
@RequiredArgsConstructor
public class HomeboxConnectionProvider implements ConnectionProvider {

    private final RestClient.Builder restClientBuilder;

    private final ConnectionRepository cRepository;

    @Override
    public void checkCredentials(ConnectionRequest request) {
        if (request.username() == null || request.password() == null) {
            List<String> missingFields = new ArrayList<>();

            if (request.username() == null) {
                missingFields.add("username");
            }
            if (request.password() == null) {
                missingFields.add("password");

            }
            throw new EmptyCredentialsException(List.copyOf(missingFields));
        }
    }

    @Override
    public ServiceType getServiceType() {
        return ServiceType.HOMEBOX;
    }

    @Override
    public ConnectionResponse authenticate(ConnectionRequest request) {
        Map<String, Object> homeboxPayload = Map.of("username", request.username(), "password",
                request.password(), "stayLoggedIn", request.stayLoggedIn());

        HomeboxLoginResponse hbResponse = restClientBuilder.baseUrl(request.appUrl()).build().post()
                .uri(HOMEBOX_LOGIN.getValue()).body(homeboxPayload).retrieve()
                .body(HomeboxLoginResponse.class);

        if (hbResponse == null) {
            throw new RemoteApiException(request.appUrl(), HOMEBOX_LOGIN.getValue());
        }

        Map<String, Object> attachmentToken = new HashMap<>();

        attachmentToken.put("attachmentToken", hbResponse.attachmentToken());

        String hbRawToken = hbResponse.token();

        String token = hbRawToken.startsWith("Bearer ") ? hbRawToken.substring(7) : hbRawToken;

        return new ConnectionResponse(token, hbResponse.expiresAt(), attachmentToken);
    }

    @Override
    public ConnectionEntity findUniqueConnectionEntry(ConnectionRequest request) {

        return cRepository.findByAppUrlAndUsername(request.appUrl(), request.username());
    }

    @Override
    public ConnectionEntity connectionToEntity(ConnectionRequest request,
            ConnectionResponse response) {
        return HomeboxConnectionEntity.from(request, response);
    }

    @Override
    public void updateToRepository(ConnectionEntity existing, ConnectionResponse response) {

        if (existing instanceof HomeboxConnectionEntity hbE) {

            hbE.setToken(response.token());
            hbE.setExpiresAt(response.expiresAt());
            hbE.setAttachmentToken(response.getExtraVar("attachmentToken"));

            cRepository.save(hbE);
        }
    }

    @Override
    public Instant getTokenExpiry(ConnectionEntity entity) {
        return (entity instanceof HomeboxConnectionEntity he) ? he.getExpiresAt() : null;
    }

    private record HomeboxLoginResponse(String token, String attachmentToken, Instant expiresAt) {
    }


}
