package io.delphiplatform.api.integration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.testcontainers.junit.jupiter.Container;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import io.delphiplatform.api.integration.client.TestAPIClient;
import io.delphiplatform.api.integration.config.DelphiTestcontainer;
import io.delphiplatform.api.integration.container.DelphiBigtableContainer;
import io.delphiplatform.api.integration.container.DelphiPostgreSQLContainer;
import io.delphiplatform.api.integration.context.bigtable.BigtableTestDataExecutorMapper;
import io.delphiplatform.api.integration.manager.TestBigtableManager;
import io.delphiplatform.api.integration.manager.TestPostgreSQLManager;
import io.delphiplatform.api.utils.TestUtils;

@DelphiTestcontainer
public abstract class BaseIT {

    @Container
    protected static final DelphiPostgreSQLContainer pgContainer = DelphiPostgreSQLContainer.getInstance();
    @Container
    protected static final DelphiBigtableContainer btContainer = DelphiBigtableContainer.getInstance();

    @Autowired
    protected TestAPIClient apiClient;
    @Autowired
    protected TestBigtableManager bigtableManager;
    @Autowired
    protected TestPostgreSQLManager postgresManager;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private BigtableTestDataExecutorMapper bigtableTestDataExecutorMapper;

    /**
     * Populate BT table from json-formatted files.
     *
     * @param tableName BT table to populate
     * @param jsons     JSON file references
     */
    protected void executeBigtableScripts(String tableName, String... jsons) {
        List<Resource> jsonResources = TestUtils.getClasspathResources(jsons);
        jsonResources.stream()
            .map(resource -> new EncodedResource(resource, "UTF-8"))
            .forEach(resource -> bigtableTestDataExecutorMapper
                .executorForTable(tableName)
                .populate(resource));
    }

    /**
     * Execute SQL statements from the file reference
     *
     * @param scripts SQL script file references
     */
    protected void executeSqlScripts(String... scripts) throws IOException {
        postgresManager.executeSqlScripts(
            TestUtils.getClasspathFiles(scripts).stream()
                .map(TestUtils::readFileAsString)
                .collect(Collectors.toList())
        );
    }

    /**
     * Execute inline SQL update statement. Example: "UPDATE tableName SET field=value"
     */
    protected void executeSqlUpdate(String statement) {
        postgresManager.executeUpdateNative(statement);
    }

    /**
     * Execute inline SQL query statement. Example: "SELECT * FROM tableName WHERE field=value"
     */
    private List<?> executeSqlQuery(String statement) {
        return postgresManager.queryNative(statement);
    }
}
