package org.carlspring.strongbox.controllers.layout.npm;

import org.carlspring.strongbox.artifact.coordinates.NpmArtifactCoordinates;
import org.carlspring.strongbox.config.IntegrationTest;
import org.carlspring.strongbox.providers.io.RepositoryFiles;
import org.carlspring.strongbox.providers.io.RepositoryPath;
import org.carlspring.strongbox.rest.common.NpmRestAssuredBaseTest;
import org.carlspring.strongbox.storage.repository.Repository;
import org.carlspring.strongbox.testing.artifact.ArtifactManagementTestExecutionListener;
import org.carlspring.strongbox.testing.artifact.NpmTestArtifact;
import org.carlspring.strongbox.testing.repository.NpmRepository;
import org.carlspring.strongbox.testing.storage.repository.RepositoryManagementTestExecutionListener;

import java.nio.file.Files;
import java.nio.file.Path;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import static org.hamcrest.CoreMatchers.equalTo;

/**
 * @author Pablo Tirado
 */
@IntegrationTest
public class NpmArtifactControllerTest
        extends NpmRestAssuredBaseTest
{

    private static final String REPOSITORY_RELEASES = "npm-releases-test";

    @Override
    @BeforeEach
    public void init()
            throws Exception
    {
        super.init();
    }

    @ExtendWith({ RepositoryManagementTestExecutionListener.class,
                  ArtifactManagementTestExecutionListener.class })
    @Test
    public void testViewPackage(@NpmRepository(repositoryId = REPOSITORY_RELEASES)
                                        Repository repository,
                                @NpmTestArtifact(repositoryId = REPOSITORY_RELEASES,
                                        id = "npm-test-view",
                                        versions = "1.0.0",
                                        scope = "@carlspring")
                                        Path packagePath)
            throws Exception
    {
        final String storageId = repository.getStorage().getId();
        final String repositoryId = repository.getId();

        RepositoryPath normPackagePath = (RepositoryPath) packagePath.normalize();
        NpmArtifactCoordinates coordinates = (NpmArtifactCoordinates) RepositoryFiles.readCoordinates(normPackagePath);

        // View OK
        String url = getContextBaseUrl() + "/storages/{storageId}/{repositoryId}/{artifactId}/{version}";
        mockMvc.contentType(MediaType.APPLICATION_JSON_VALUE)
               .when()
               .get(url, storageId, repositoryId, coordinates.getId(), coordinates.getVersion())
               .peek()
               .then()
               .statusCode(HttpStatus.OK.value());

        // View 404
        mockMvc.contentType(MediaType.APPLICATION_JSON_VALUE)
               .when()
               .get(url, storageId, repositoryId, coordinates.getId(), "1.0.1")
               .peek()
               .then()
               .statusCode(HttpStatus.NOT_FOUND.value());
    }

    @ExtendWith({ RepositoryManagementTestExecutionListener.class,
                  ArtifactManagementTestExecutionListener.class })
    @Test
    public void testPackageCommonFlow(@NpmRepository(repositoryId = REPOSITORY_RELEASES)
                                              Repository repository,
                                      @NpmTestArtifact(id = "npm-test-release",
                                              versions = "1.0.0",
                                              scope = "@carlspring")
                                              Path packagePath)
            throws Exception
    {
        final String storageId = repository.getStorage().getId();
        final String repositoryId = repository.getId();
        final String packageId = "@carlspring/npm-test-release";
        final String packageVersion = "1.0.0";

        NpmArtifactCoordinates coordinates = NpmArtifactCoordinates.of(packageId, packageVersion);

        Path publishJsonPath = packagePath.resolveSibling("publish.json");
        byte[] publishJsonContent = Files.readAllBytes(publishJsonPath);

        //Publish
        String url = getContextBaseUrl() + "/storages/{storageId}/{repositoryId}/{artifactId}";
        mockMvc.contentType(MediaType.APPLICATION_JSON_VALUE)
               .body(publishJsonContent)
               .when()
               .put(url, storageId, repositoryId, coordinates.getId())
               .peek()
               .then()
               .statusCode(HttpStatus.OK.value());

        //View
        mockMvc.contentType(MediaType.APPLICATION_JSON_VALUE)
               .when()
               .get(url, storageId, repositoryId, coordinates.getId())
               .peek()
               .then()
               .statusCode(HttpStatus.OK.value());

        //Download
        mockMvc.contentType(MediaType.APPLICATION_JSON_VALUE)
               .when()
               .get(url, storageId, repositoryId, coordinates.toResource())
               .then()
               .statusCode(HttpStatus.OK.value())
               .assertThat()
               .header(HttpHeaders.CONTENT_LENGTH, equalTo(String.valueOf(Files.size(packagePath))));
    }

    @ExtendWith({ RepositoryManagementTestExecutionListener.class,
                  ArtifactManagementTestExecutionListener.class })
    @Test
    public void addUserTest(@NpmRepository(repositoryId = REPOSITORY_RELEASES)
                                    Repository repository)
    {
        String url = getContextBaseUrl() + "/storages/{storageId}/{repositoryId}/-/user/org.couchdb.user:{username}";

        final String storageId = repository.getStorage().getId();
        final String repositoryId = repository.getId();

        NpmUser strongboxUser = createNpmUser("admin", "password");
        NpmUser nonStrongboxUser = createNpmUser("notARealUser", "notARealPassword");

        //can login with strongbox user
        mockMvc.contentType(MediaType.APPLICATION_JSON_VALUE)
               .body(strongboxUser)
               .when()
               .put(url, storageId, repositoryId, strongboxUser.getName())
               .peek()
               .then()
               .statusCode(HttpStatus.CREATED.value());

        //can't login with non-strongbox user
        mockMvc.contentType(MediaType.APPLICATION_JSON_VALUE)
               .body(nonStrongboxUser)
               .when()
               .put(url, storageId, repositoryId, nonStrongboxUser.getName())
               .peek()
               .then()
               .statusCode(HttpStatus.UNAUTHORIZED.value());

    }

    private NpmUser createNpmUser(String username,
                                  String password)
    {
        NpmUser npmUser = new NpmUser();
        npmUser.setName(username);
        npmUser.setPassword(password);
        npmUser.setDate("");
        npmUser.setId("");
        npmUser.setRoles(new String[]{});
        npmUser.setType("");

        return npmUser;
    }
}

@@ -1707,32 +1707,24 @@
             
-        
 Repository r
@@ -1726,32 +1726,32 @@
 ory repository,%0A
+
                 
@@ -1859,16 +1859,25 @@
         
+         
 id = %22np
@@ -1890,16 +1890,25 @@
 -view%22,%0A
+         
         
@@ -1991,32 +1991,41 @@
                 
+         
 scope = %22@carlsp
@@ -2027,32 +2027,24 @@
 arlspring%22)%0A
-        
             
@@ -3373,32 +3373,24 @@
 Y_RELEASES)%0A
-        
             
@@ -3430,32 +3430,32 @@
 ory repository,%0A
+
                 
@@ -3556,32 +3556,41 @@
                 
+         
 versions = %221.0.
@@ -3585,32 +3585,41 @@
 ions = %221.0.0%22,%0A
+         
                 
@@ -3667,32 +3667,24 @@
 arlspring%22)%0A
-        
             
@@ -5534,32 +5534,24 @@
 Y_RELEASES)%0A
-        
             
@@ -5589,16 +5589,16 @@
 sitory)%0A
+
     %7B%0A  
@@ -6682,25 +6682,24 @@
 D.value());%0A
-%0A
     %7D%0A%0A    p
@@ -7068,16 +7068,21 @@
 pmUser;%0A
-
     %7D%0A
+    %0A
 %7D%0A

Update NpmArtifactControllerTest.java