/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.usergrid.rest.applications;


import com.fasterxml.jackson.databind.JsonNode;
import com.sun.jersey.api.client.UniformInterfaceException;
import org.apache.usergrid.rest.test.resource2point0.AbstractRestIT;
import org.apache.usergrid.rest.test.resource2point0.endpoints.mgmt.ManagementResponse;
import org.apache.usergrid.rest.test.resource2point0.model.*;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.jcip.annotations.NotThreadSafe;

import javax.ws.rs.core.MediaType;
import java.util.*;

import static org.junit.Assert.fail;

@NotThreadSafe
public class ApplicationDeleteIT extends AbstractRestIT {

    private static final Logger logger = LoggerFactory.getLogger(ApplicationDeleteIT.class);

    public static final int INDEXING_WAIT = 3000;

    Token orgAdminToken;
    String orgName;
    @Before
    public void setup(){
        orgAdminToken = getAdminToken( clientSetup.getUsername(), clientSetup.getUsername());
        orgName = clientSetup.getOrganization().getName();

    }

    /**
     * Test most common use cases.
     * <pre>
     *  - create app with collection of things
     *  - delete the app
     *  - test that attempts to get the app, its collections and entities throw 400 with message
     *  - test that we cannot delete the app a second time
     *  - test that we can create a new app with the same name as the deleted app
     * </pre>
     */
    @Test
    public void testBasicOperation() throws Exception {

        // create app with a collection of "things"

        List<Entity> entities = new ArrayList<>();

        String         appToDeleteName = clientSetup.getAppName() + UUID.randomUUID();
        UUID appToDeleteId = createAppWithCollection(orgName, appToDeleteName, orgAdminToken, entities);

        // delete the app

        try {
            clientSetup.getRestClient()
                .org(orgName).app(appToDeleteId.toString()).getResource()
                .queryParam("access_token", orgAdminToken.getAccessToken())
                .delete();

            fail("Delete must fail without app_delete_confirm parameter");

        } catch ( Exception e ) {
            logger.error("Error", e);
        }

        clientSetup.getRestClient()
            .org(orgName).app(appToDeleteId.toString() ).getResource()
            .queryParam("access_token", orgAdminToken.getAccessToken() )
            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
            .delete();

        // test that we can no longer get the app

        try {
            clientSetup.getRestClient()
                .org(orgName).app(appToDeleteName).getResource()
                .queryParam("access_token", orgAdminToken.getAccessToken())
                .type(MediaType.APPLICATION_JSON)
                .get(ApiResponse.class);

            fail("Must not be able to get deleted app");

        } catch ( UniformInterfaceException expected ) {
            Assert.assertEquals("Error must be 400", 400, expected.getResponse().getStatus() );
            JsonNode node = mapper.readTree( expected.getResponse().getEntity( String.class ));
            Assert.assertEquals("organization_application_not_found", node.get("error").textValue());
        }

        // test that we can no longer get deleted app's collection

        try {
            clientSetup.getRestClient()
                .org(orgName).app(appToDeleteName).collection("things").getResource()
                .queryParam("access_token", orgAdminToken.getAccessToken() )
                .type(MediaType.APPLICATION_JSON )
                .get(ApiResponse.class);

            fail("Must not be able to get deleted app's collection");

        } catch ( UniformInterfaceException expected ) {
            Assert.assertEquals("Error must be 400", 400, expected.getResponse().getStatus() );
            JsonNode node = mapper.readTree( expected.getResponse().getEntity( String.class ));
            Assert.assertEquals("organization_application_not_found", node.get("error").textValue());
        }

        // test that we can no longer get an app entity

        try {
            UUID entityId = entities.get(0).getUuid();
            clientSetup.getRestClient()
                .org(orgName).app(appToDeleteName).collection("things").entity( entityId ).getResource()
                .queryParam( "access_token", orgAdminToken.getAccessToken())
                .type( MediaType.APPLICATION_JSON)
                .get(ApiResponse.class);

            fail("Must not be able to get deleted app entity");

        } catch ( UniformInterfaceException expected ) {
            // TODO: why not a 404?
            Assert.assertEquals("Error must be 400", 400, expected.getResponse().getStatus() );
            JsonNode node = mapper.readTree( expected.getResponse().getEntity( String.class ));
            Assert.assertEquals("organization_application_not_found", node.get("error").textValue());
        }

        // test that we cannot see the application in the list of applications returned
        // by the management resource's get organization's applications end-point

        refreshIndex();

        ManagementResponse orgAppResponse = clientSetup.getRestClient()
            .management().orgs().organization( orgName ).apps().getOrganizationApplications();

        for ( String appName : orgAppResponse.getData().keySet() ) {
            if ( orgAppResponse.getData().get( appName ).equals( appToDeleteId.toString() )) {
                fail("Deleted app must not be included in list of org apps");
            }
        }

        // test that we cannot delete the application a second time

        try {
            clientSetup.getRestClient()
                .org(orgName).app(appToDeleteId.toString()).getResource()
                .queryParam("access_token", orgAdminToken.getAccessToken())
                .delete();

        } catch ( UniformInterfaceException expected ) {
            Assert.assertEquals("Error must be 404", 404, expected.getResponse().getStatus() );
            JsonNode node = mapper.readTree( expected.getResponse().getEntity( String.class ));
            Assert.assertEquals("not_found", node.get("error").textValue());
        }

        // test that we can create a new application with the same name

        ApiResponse appCreateAgainResponse = clientSetup.getRestClient()
            .management().orgs().organization( orgName ).app().getResource()
            .queryParam( "access_token", orgAdminToken.getAccessToken() )
            .type( MediaType.APPLICATION_JSON )
            .post( ApiResponse.class, new Application( appToDeleteName ) );

        Assert.assertEquals("Must be able to create app with same name as deleted app",
            (orgName + "/" + appToDeleteName).toLowerCase(),
            appCreateAgainResponse.getEntities().get(0).get("name"));
    }


    /**
     * Test restore of deleted app.
     * <pre>
     *  - create app with collection of things
     *  - delete the app
     *  - restore the app
     *  - test that we can get the app, its collections and an entity
     * </pre>
     */
    @Test
    public void testAppRestore() throws Exception {
        String         appToDeleteName = clientSetup.getAppName() + UUID.randomUUID();

        // create app with a collection of "things"
        List<Entity> entities = new ArrayList<>();

        UUID appToDeleteId = createAppWithCollection(orgName, appToDeleteName, orgAdminToken, entities);

        // delete the app

        logger.debug("\n\nDeleting app\n");

        clientSetup.getRestClient()
            .org(orgName).app( appToDeleteName ).getResource()
            .queryParam("access_token", orgAdminToken.getAccessToken() )
            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
            .delete();

        refreshIndex();


        // restore the app

        logger.debug("\n\nRestoring app\n");

        clientSetup.getRestClient()
            .org(orgName).app( appToDeleteId.toString() ).getResource()
            .queryParam("access_token", orgAdminToken.getAccessToken() )
            .put();

        refreshIndex();

        // test that we can see the application in the list of applications

        logger.debug("\n\nGetting app list from management end-point\n");

        ManagementResponse orgAppResponse = clientSetup.getRestClient()
            .management().orgs().organization( orgName ).apps().getOrganizationApplications();

        boolean found = false;
        for ( String appName : orgAppResponse.getData().keySet() ) {
            if ( orgAppResponse.getData().get( appName ).equals( appToDeleteId.toString() )) {
                found = true;
                break;
            }
        }

        Assert.assertTrue( found );

        // test that we can get an app entity

        logger.debug("\n\nGetting entities from app\n");

        UUID entityId = entities.get(0).getUuid();
        ApiResponse entityResponse = clientSetup.getRestClient()
            .org(orgName).app(appToDeleteName).collection("things").entity( entityId ).getResource()
            .queryParam("access_token", orgAdminToken.getAccessToken())
            .type(MediaType.APPLICATION_JSON)
            .get(ApiResponse.class);
        Assert.assertEquals( entityId, entityResponse.getEntities().get(0).getUuid() );

        // test that we can get deleted app's collection

        ApiResponse collectionReponse = clientSetup.getRestClient()
            .org(orgName).app(appToDeleteName).collection("things").getResource()
            .queryParam("access_token", orgAdminToken.getAccessToken())
            .type(MediaType.APPLICATION_JSON)
            .get(ApiResponse.class);
        Assert.assertEquals( entities.size(), collectionReponse.getEntityCount() );
    }


    /**
     * Test that we cannot restore deleted app with same name as
     */
    @Test
    public void testAppRestoreConflict() throws Exception {
        String         appToDeleteName = clientSetup.getAppName() + UUID.randomUUID();

        // create app with a collection of "things"
        List<Entity> entities = new ArrayList<>();

        UUID appToDeleteId = createAppWithCollection(orgName, appToDeleteName, orgAdminToken, entities);

        // delete the app

        clientSetup.getRestClient()
            .org( orgName ).app(appToDeleteId.toString() ).getResource()
            .queryParam( "access_token", orgAdminToken.getAccessToken() )
            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
            .delete();
        refreshIndex();

        // create new app with same name

        createAppWithCollection(orgName, appToDeleteName, orgAdminToken, entities);

        // attempt to restore original app, should get 409

        try {

            clientSetup.getRestClient()
                .org(orgName).app(appToDeleteId.toString()).getResource()
                .queryParam("access_token", orgAdminToken.getAccessToken())
                .put();

            fail("Must fail to restore app with same name as existing app");

        } catch ( UniformInterfaceException e ) {
            Assert.assertEquals(409, e.getResponse().getStatus());
        }
    }


    /**
     * Test that we cannot delete an app with same name as an app that is already deleted.
     * TODO: investigate way to support this, there should be no such restriction.
     */
    @Test
    public void testAppDeleteConflict() throws Exception {
        String         appToDeleteName = clientSetup.getAppName() + UUID.randomUUID();

        // create app with a collection of "things"

        String orgName = clientSetup.getOrganization().getName();
        Token orgAdminToken = getAdminToken( clientSetup.getUsername(), clientSetup.getUsername());

        List<Entity> entities = new ArrayList<>();

        UUID appToDeleteId = createAppWithCollection(orgName, appToDeleteName, orgAdminToken, entities);

        // delete the app

        clientSetup.getRestClient()
            .org( orgName ).app(appToDeleteId.toString() ).getResource()
            .queryParam( "access_token", orgAdminToken.getAccessToken() )
            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
            .delete();
        refreshIndex();
        // create new app with same name

        UUID newAppId = createAppWithCollection(orgName, appToDeleteName, orgAdminToken, entities);

        // attempt to delete new app, it should fail

        try {

            clientSetup.getRestClient()
                .org(orgName).app( newAppId.toString() ).getResource()
                .queryParam("access_token", orgAdminToken.getAccessToken())
                .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
                .delete();

            fail("Must fail to delete app with same name as deleted app");

        } catch ( UniformInterfaceException e ) {
            Assert.assertEquals( 409, e.getResponse().getStatus() );
        }
    }


    private UUID createAppWithCollection(
        String orgName, String appName, Token orgAdminToken, List<Entity> entities) {

        ApiResponse appCreateResponse = clientSetup.getRestClient()
            .management().orgs().organization( orgName ).app().getResource()
            .queryParam( "access_token", orgAdminToken.getAccessToken() )
            .type( MediaType.APPLICATION_JSON )
            .post( ApiResponse.class, new Application( appName ) );
        UUID appId = appCreateResponse.getEntities().get(0).getUuid();

        try { Thread.sleep(INDEXING_WAIT); } catch (InterruptedException ignored ) { }

        for ( int i=0; i<10; i++ ) {

            final String entityName = "entity" + i;
            Entity entity = new Entity();
            entity.setProperties(new HashMap<String, Object>() {{
                put("name", entityName );
            }});

            ApiResponse createResponse = clientSetup.getRestClient()
                .org(orgName).app( appName ).collection("things").getResource()
                .queryParam("access_token", orgAdminToken.getAccessToken())
                .type(MediaType.APPLICATION_JSON)
                .post( ApiResponse.class, entity );

            entities.add( createResponse.getEntities().get(0) );
        }
        refreshIndex();
        return appId;
    }
}

