package dev.fitko.fitconnect.integrationtests;

import dev.fitko.fitconnect.api.config.ApplicationConfig;
import dev.fitko.fitconnect.api.config.Environment;
import dev.fitko.fitconnect.api.config.EnvironmentName;
import dev.fitko.fitconnect.api.config.SenderConfig;
import dev.fitko.fitconnect.api.config.SubscriberConfig;
import dev.fitko.fitconnect.api.domain.model.event.problems.Problem;
import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
import dev.fitko.fitconnect.client.SubscriberClient;
import dev.fitko.fitconnect.client.bootstrap.ClientFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Stream;

import static dev.fitko.fitconnect.api.domain.model.event.problems.Problem.SCHEMA_URL;

public class IntegrationTestBase {

    private static final String authBaseUrl = "https://auth-testing.fit-connect.fitko.dev";
    private static final String routingBaseUrl = "https://routing-api-testing.fit-connect.fitko.dev";
    private static final String selfServicePortalUrl = "https://portal.auth-testing.fit-connect.fitko.dev";
    private static final String submissionBaseUrl = "https://submission-api-testing.fit-connect.fitko.dev";

    public static void cleanupTestSubmissions() {

        final UUID jsonDataDestinationId = UUID.fromString(System.getenv("TEST_DESTINATION_ID_JSON_DATA"));
        final UUID xmlDataDestinationId = UUID.fromString(System.getenv("TEST_DESTINATION_ID_XML_DATA"));

        final Problem problem = new Problem(SCHEMA_URL + "technical-error", "cleanup", "submission-cleanup", "other");
        final SubscriberClient subscriberClient = ClientFactory.getSubscriberClient(getConfigWithCredentialsFromEnvironment("TEST", true));

        final Set<SubmissionForPickup> jsonSubmissions = subscriberClient.getAvailableSubmissionsForDestination(jsonDataDestinationId);
        final Set<SubmissionForPickup> xmlSubmissions = subscriberClient.getAvailableSubmissionsForDestination(xmlDataDestinationId);

        Stream.concat(jsonSubmissions.stream(), xmlSubmissions.stream()).forEach((s -> {
            try {
                subscriberClient.rejectSubmission(s, List.of(problem));
            } catch (final Exception e) {
                //continue
            }
        }));
    }

    public static ApplicationConfig getConfigWithCredentialsFromEnvironment(final String environmentName, final boolean allowInsecurePublicKey) {

        return getConfigWithCredentialsFromEnvironment(environmentName, allowInsecurePublicKey, Collections.emptyMap());
    }

    public static ApplicationConfig getConfigWithCredentialsFromEnvironment(final String environmentName, final boolean allowInsecurePublicKey, final Map<String,String> submissionDataSchemas) {

        final var sender = new SenderConfig(System.getenv("SENDER_CLIENT_ID"), System.getenv("SENDER_CLIENT_SECRET"));

        final var subscriber = SubscriberConfig.builder()
                .clientId(System.getenv("SUBSCRIBER_CLIENT_ID"))
                .clientSecret(System.getenv("SUBSCRIBER_CLIENT_SECRET"))
                .privateDecryptionKeyPaths(List.of("src/test/resources/private_decryption_test_key.json"))
                .privateSigningKeyPath("src/test/resources/private_test_signing_key.json")
                .build();

        final EnvironmentName envName = new EnvironmentName(environmentName);
        final Environment env = new Environment(authBaseUrl, routingBaseUrl, List.of(submissionBaseUrl), selfServicePortalUrl, true, allowInsecurePublicKey, false);

        return ApplicationConfig.builder()
                .senderConfig(sender)
                .subscriberConfig(subscriber)
                .environments(Map.of(envName, env))
                .activeEnvironment(envName)
                .submissionDataSchemas(submissionDataSchemas)
                .build();
    }

    String getResourceAsString(final String filename) throws IOException {
        return new String(IntegrationTestBase.class.getResourceAsStream(filename).readAllBytes());
    }
}