/*
 * 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.management;


import com.fasterxml.jackson.databind.JsonNode;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.representation.Form;
import org.apache.commons.lang.RandomStringUtils;

import org.apache.usergrid.persistence.index.utils.UUIDUtils;
import org.apache.usergrid.rest.management.organizations.OrganizationsResource;
import org.apache.usergrid.rest.test.resource2point0.AbstractRestIT;
import org.apache.usergrid.rest.test.resource2point0.model.*;
import org.apache.usergrid.rest.test.resource2point0.model.Collection;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import static org.apache.usergrid.rest.AbstractRestIT.logNode;
import static org.apache.usergrid.rest.management.ManagementResource.USERGRID_CENTRAL_URL;
import static org.apache.usergrid.utils.MapUtils.hashMap;
import static org.junit.Assert.*;

/**
 * @author tnine
 */
public class ManagementResourceIT extends AbstractRestIT {

    private static final Logger logger = LoggerFactory.getLogger(ManagementResourceIT.class);
    private org.apache.usergrid.rest.test.resource2point0.endpoints.mgmt.ManagementResource management;

    public ManagementResourceIT() throws Exception {

    }


    @Before
    public void setup() {
        management= clientSetup.getRestClient().management();
        Token token = management.token().get(new QueryParameters().addParam("grant_type", "password").addParam("username", clientSetup.getEmail()).addParam("password", clientSetup.getPassword()));
        management.token().setToken(token);
    }

    /**
     * Test if we can reset our password as an admin
     */
    @Test
    public void setSelfAdminPasswordAsAdwmin() {
        UUID uuid =  UUIDUtils.newTimeUUID();
        management.token().setToken(clientSetup.getSuperuserToken());
        management.orgs().org( clientSetup.getOrganizationName() ).users().post(ApiResponse.class, new User("test" + uuid, "test" + uuid, "test" + uuid + "@email.com", "test"));
        Map<String, Object> data = new HashMap<>();
        data.put( "newpassword", "foo" );
        data.put( "oldpassword", "test" );
        management.users().user("test"+uuid).password().post(Entity.class, data);
        Token token = management.token().post(Token.class, new Token( "test"+uuid, "foo" ) );
        management.token().setToken( token );
        data.clear();
        data.put( "oldpassword", "foo" );
        data.put( "newpassword", "test" );
        management.users().user("test"+uuid).password().post(Entity.class,data);
    }


    /**
     * Test that admins can't view organizations they're not authorized to view.
     */
    @Test
    public void crossOrgsNotViewable() throws Exception {

        String username = "test" + UUIDUtils.newTimeUUID();
        String name = "someguy2";
        String email = "someguy" + "@usergrid.com";
        String password = "password";
        String orgName = "someneworg";

        Entity payload =
                new Entity().chainPut("company", "Apigee" );

        Organization organization = new Organization(orgName,username,email,name,password,payload);

        Organization node = management().orgs().post(  organization );
        management.token().get(clientSetup.getUsername(),clientSetup.getPassword());

        // check that the test admin cannot access the new org info

        Status status = null;
        String returnVal = "";

        try {
            returnVal = this.management().orgs().org( orgName ).get(String.class);
        }
        catch ( UniformInterfaceException uie ) {
            status = uie.getResponse().getClientResponseStatus();
        }

        assertNotNull( status );
        assertEquals( Status.UNAUTHORIZED, status );

        // this admin should have access to test org
        status = null;
        try {
            this.management().orgs().org( this.clientSetup.getOrganizationName() ).get( String.class );
        }
        catch ( UniformInterfaceException uie ) {
            status = uie.getResponse().getClientResponseStatus();
        }

        assertNull( status );

        //test getting the organization by org

        status = null;
        try {
            this.management().orgs().org( this.clientSetup.getOrganizationName() ).get( String.class );
        }
        catch ( UniformInterfaceException uie ) {
            status = uie.getResponse().getClientResponseStatus();
        }

        assertNull( status );
    }


    /**
     * Test that we can support over 10 items in feed.
     */
    @Test
    public void mgmtFollowsUserFeed() throws Exception {
        List<String> users1 = new ArrayList<String>();
        int i;
        //try with 10 users
        for ( i = 0; i < 10; i++ ) {
            users1.add( "follower" + Integer.toString( i ) );
        }

        refreshIndex(  );

        checkFeed( "leader1", users1 );
        //try with 11
        List<String> users2 = new ArrayList<String>();
        for ( i = 20; i < 31; i++ ) {
            users2.add( "follower" + Integer.toString( i ) );
        }
        checkFeed( "leader2", users2 );
    }


    private void checkFeed( String leader, List<String> followers ) throws IOException {
        List<Entity> userFeed;

        //create user
        createUser( leader );
        refreshIndex(   );

        String preFollowContent = leader + ": pre-something to look for " + UUID.randomUUID().toString();

        addActivity( leader, leader + " " + leader + "son", preFollowContent );
        refreshIndex(  );

        String lastUser = followers.get( followers.size() - 1 );
        int i = 0;
        for ( String user : followers ) {
            createUser( user );
            refreshIndex( );
            follow( user, leader );
            refreshIndex(  );
        }
        userFeed = getUserFeed( lastUser );
        assertTrue( userFeed.size() == 1 );

        //retrieve feed
        userFeed = getUserFeed( lastUser );
        assertTrue( userFeed.size() == 1 );
        String postFollowContent = leader + ": something to look for " + UUID.randomUUID().toString();
        addActivity( leader, leader + " " + leader + "son", postFollowContent );

        refreshIndex(  );

        //check feed
        userFeed = getUserFeed( lastUser );
        assertNotNull( userFeed );
        assertTrue( userFeed.size() > 1 );
        String serialized = ((Entity)userFeed.get(0)).get("content").toString()+ ((Entity)userFeed.get(1)).get("content").toString();
        assertTrue( serialized.indexOf( postFollowContent ) >= 0 );
        assertTrue( serialized.indexOf( preFollowContent ) >= 0 );
    }


    private void createUser( String username ) {
        Map<String, Object> payload = new LinkedHashMap<String, Object>();
        payload.put( "username", username );
       this.app().collection("users").post(String.class, payload);
    }


    private List<Entity> getUserFeed( String username ) throws IOException {
        Collection collection = this.app().collection("users").entity(username).collection("feed").get();
        return collection.getResponse().getEntities();
    }


    private void follow( String user, String followUser ) {
        //post follow
        Entity entity = this.app().collection("users").entity(user).collection("following").collection("users").entity(followUser).post();
    }


    private void addActivity( String user, String name, String content ) {
        Map<String, Object> activityPayload = new HashMap<String, Object>();
        activityPayload.put( "content", content );
        activityPayload.put( "verb", "post" );
        Map<String, String> actorMap = new HashMap<String, String>();
        actorMap.put( "displayName", name );
        actorMap.put( "username", user );
        activityPayload.put("actor", actorMap);
        Entity entity = this.app().collection("users").entity(user).collection("activities").post(new Entity(activityPayload));
    }


    @Test
    public void mgmtCreateAndGetApplication() throws Exception {



        // POST /applications
        ApiResponse apiResponse = management().orgs().org( clientSetup.getOrganizationName() ).app().post(new Application("mgmt-org-app"));


        refreshIndex();

        Entity appdata = apiResponse.getEntities().get(0);
        assertEquals((clientSetup.getOrganizationName() + "/mgmt-org-app").toLowerCase(), appdata.get("name").toString().toLowerCase());
        assertNotNull(appdata.get("metadata"));
        Map metadata =(Map) appdata.get( "metadata" );
        assertNotNull(metadata.get("collections"));
        Map collections =  ((Map)metadata.get("collections"));
        assertNotNull(collections.get("roles"));
        Map roles =(Map) collections.get("roles");
        assertNotNull(roles.get("title"));
        assertEquals("Roles", roles.get("title").toString());
        assertEquals(4, roles.size());

        refreshIndex(   );

        // GET /applications/mgmt-org-app


        Entity app = management().orgs().org( clientSetup.getOrganizationName() ).app().addToPath("mgmt-org-app").get();


        assertEquals(this.clientSetup.getOrganizationName().toLowerCase(), app.get("organizationName").toString());
        assertEquals( "mgmt-org-app", app.get( "applicationName" ).toString() );

        assertEquals( clientSetup.getOrganizationName().toLowerCase() + "/mgmt-org-app", app.get( "name" ).toString() );
        metadata =(Map) appdata.get( "metadata" );
        collections =  ((Map)metadata.get("collections"));
        roles =(Map) collections.get("roles");

        assertEquals( "Roles", roles.get("title").toString() );
        assertEquals(4, roles.size());
    }

    @Test
    public void tokenTtl() throws Exception {

        long ttl = 2000;

        Token token = management.token().get(new QueryParameters().addParam("grant_type", "password").addParam("username", clientSetup.getEmail()).addParam("password", clientSetup.getPassword()).addParam("ttl", String.valueOf(ttl)));


        long startTime = System.currentTimeMillis();


        assertNotNull( token );

        Entity userdata = management.users().entity(clientSetup.getEmail()).get(token);

        assertNotNull(userdata.get("email").toString());

        // wait for the token to expire
        Thread.sleep(  (System.currentTimeMillis() - startTime) + ttl );

        Status responseStatus = null;
        try {
            userdata = management.users().user(clientSetup.getEmail()).get();
        }
        catch ( UniformInterfaceException uie ) {
            responseStatus = uie.getResponse().getClientResponseStatus();
        }

        assertEquals( Status.UNAUTHORIZED, responseStatus );
    }


    @Test
    public void token() throws Exception {
        Token myToken = management.token().get(new QueryParameters().addParam("grant_type", "password").addParam("username", clientSetup.getEmail()).addParam("password", clientSetup.getPassword()));

        String token = myToken.getAccessToken();
        assertNotNull( token );

        // set an organization property
        Organization payload = new Organization();
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put( "securityLevel", 5 );
        payload.put( OrganizationsResource.ORGANIZATION_PROPERTIES, properties );
        management.orgs().org( clientSetup.getOrganizationName() )
            .put(payload);


        // ensure the organization property is included
        String obj = management.token().get(String.class,new QueryParameters().addParam("access_token", token));
        assertTrue(obj.indexOf("securityLevel")>0);
    }


    @Test
    public void meToken() throws Exception {
        QueryParameters queryParameters = new QueryParameters().addParam("grant_type", "password")
                                  .addParam("username", clientSetup.getUsername()).addParam("password",clientSetup.getPassword());
        Token myToken = management.me().get(Token.class,queryParameters);


        String token = myToken.getAccessToken();
        assertNotNull( token );

        Entity entity = management.me().get( Entity.class );

        assertNotNull( entity.get( "passwordChanged" ) );
        assertNotNull( entity.get( "access_token" ) );
        assertNotNull( entity.get( "expires_in" ) );
        Map<String,Object> userNode =(Map<String,Object>) entity.get( "user" );
        assertNotNull( userNode );
        assertNotNull( userNode.get( "uuid" ) );
        assertNotNull( userNode.get( "username" ) );
        assertNotNull( userNode.get( "email" ) );
        assertNotNull( userNode.get( "name" ) );
        assertNotNull( userNode.get( "properties" ) );
        Map<String,Object> orgsNode = (Map<String,Object>) userNode.get( "organizations" );
        assertNotNull( orgsNode );
        Map<String,Object> orgNode =(Map<String,Object>) orgsNode.entrySet().iterator().next().getValue();
        assertNotNull( orgNode );
        assertNotNull( orgNode.get( "name" ) );
        assertNotNull( orgNode.get( "properties" ) );
    }


    @Test
    public void meTokenPost() throws Exception {
        Map<String, String> payload =
                hashMap( "grant_type", "password" ).map( "username", clientSetup.getUsername() ).map( "password",clientSetup.getPassword() );

        JsonNode node = management.me().post(JsonNode.class, payload);

        logNode( node );
        String token = node.get( "access_token" ).textValue();

        assertNotNull( token );

        node = management.me().get( JsonNode.class );
    }


    @Test
    public void meTokenPostForm() {

        Form form = new Form();
        form.add( "grant_type", "password" );
        form.add( "username", clientSetup.getUsername() );
        form.add( "password", clientSetup.getPassword() );

        JsonNode node = management.me().post( JsonNode.class, form );

        logNode( node );
        String token = node.get( "access_token" ).textValue();

        assertNotNull( token );

        node = resource().path( "/management/me" ).queryParam( "access_token", token )
                         .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
        logNode( node );
    }


    @Test
    public void ttlNan() throws Exception {

        Map<String, String> payload =
                hashMap( "grant_type", "password" ).map("username", clientSetup.getUsername()).map( "password",clientSetup.getPassword() )
                                                   .map("ttl", "derp");

        Status responseStatus = null;
        try {
           management.token().post(JsonNode.class, payload);
        }
        catch ( UniformInterfaceException uie ) {
            responseStatus = uie.getResponse().getClientResponseStatus();
        }

        assertEquals( Status.BAD_REQUEST, responseStatus );
    }


    @Test
    public void ttlOverMax() throws Exception {

        Map<String, String> payload =
                hashMap( "grant_type", "password" ).map( "username", clientSetup.getUsername()).map( "password", clientSetup.getPassword() )
                                                   .map( "ttl", Long.MAX_VALUE + "" );

        Status responseStatus = null;

        try {
            management.token().post(JsonNode.class, payload);
        }
        catch ( UniformInterfaceException uie ) {
            responseStatus = uie.getResponse().getClientResponseStatus();
        }

        assertEquals( Status.BAD_REQUEST, responseStatus );
    }


    @Test
    public void revokeToken() throws Exception {
        Token token1 = management.token().get(clientSetup.getUsername(),clientSetup.getPassword());

        Entity response = management.users().user(clientSetup.getUsername()).get();

        assertNotNull(response.get("email").toString());

        response =   management.users().user(clientSetup.getUsername()).get();

        assertNotNull(response.get("email").toString());

        // now revoke the tokens
        response = management.users().user(clientSetup.getUsername()).revokeTokens().post(true,Entity.class,null, null,false);

        // the tokens shouldn't work

        Status status = null;

        try {
            response = management.users().user(clientSetup.getUsername()).get();
        }
        catch ( UniformInterfaceException uie ) {
            status = uie.getResponse().getClientResponseStatus();
        }

        assertEquals( Status.UNAUTHORIZED, status );

        Token token3 = management.token().get(clientSetup.getUsername(), clientSetup.getPassword());

        response = management.users().user(clientSetup.getUsername()).get();
        assertNotNull(response.get("email").toString());

        // now revoke the token3
        QueryParameters queryParameters = new QueryParameters();
        queryParameters.addParam( "token", token3.getAccessToken() );
        management.users().user(clientSetup.getUsername()).revokeToken().post( false, Entity.class,null,queryParameters );

        // the token3 shouldn't work
        status = null;

        try {
            management.users().user(clientSetup.getUsername()).get();
        }
        catch ( UniformInterfaceException uie ) {
            status = uie.getResponse().getClientResponseStatus();
        }

        assertEquals( Status.UNAUTHORIZED, status );

    }


    @Test
    @Ignore
    public void testValidateExternalToken() throws Exception {

        // create a new admin user, get access token

        String rand = RandomStringUtils.randomAlphanumeric(10);
        final String username = "user_" + rand;
        management().orgs().post(
            new Organization( username, username, username+"@example.com", username, "password", null ) );

        refreshIndex();
        QueryParameters queryParams = new QueryParameters().addParam("username", username ).addParam("password", "password").addParam("grant_type", "password");
        Token accessInfoNode = management.token().get(queryParams);
        String accessToken = accessInfoNode.getAccessToken();

        // set the Usergrid Central SSO URL because Tomcat port is dynamically assigned

        String suToken = clientSetup.getSuperuserToken().getAccessToken();
        Map<String, String> props = new HashMap<String, String>();
        props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm() );
        resource().path( "/testproperties" )
                .queryParam("access_token", suToken)
                .accept( MediaType.APPLICATION_JSON )
                .type( MediaType.APPLICATION_JSON_TYPE )
                .post( props );

        // attempt to validate the token, must be valid
        queryParams = new QueryParameters().addParam("access_token", suToken ).addParam("ext_access_token", accessToken).addParam("ttl", "1000");

        Entity validatedNode = management.externaltoken().get(Entity.class,queryParams);
        String validatedAccessToken = validatedNode.get( "access_token" ).toString();
        assertEquals( accessToken, validatedAccessToken );

        // attempt to validate an invalid token, must fail

        try {
            queryParams = new QueryParameters().addParam("access_token", suToken ).addParam("ext_access_token", "rubbish_token").addParam("ttl", "1000");

            validatedNode = management.externaltoken().get(Entity.class,queryParams);

            fail("Validation should have failed");
        } catch ( UniformInterfaceException actual ) {
            assertEquals( 404, actual.getResponse().getStatus() );
            String errorMsg = actual.getResponse().getEntity( JsonNode.class ).get( "error_description" ).toString();
            logger.error( "ERROR: " + errorMsg );
            assertTrue( errorMsg.contains( "Cannot find Admin User" ) );
        }



        // TODO: how do we test the create new user and organization case?



        // unset the Usergrid Central SSO URL so it does not interfere with other tests

        props.put( USERGRID_CENTRAL_URL, "" );
        resource().path( "/testproperties" )
                .queryParam( "access_token", suToken)
                .accept( MediaType.APPLICATION_JSON )
                .type( MediaType.APPLICATION_JSON_TYPE )
                .post( props );

    }


    @Test
    @Ignore
    public void testSuperuserOnlyWhenValidateExternalTokensEnabled() throws Exception {

        // create an org and an admin user

        String rand = RandomStringUtils.randomAlphanumeric( 10 );
        final String username = "user_" + rand;
        management().orgs().post(
            new Organization( username, username, username+"@example.com", username, "password", null ) );

        // turn on validate external tokens by setting the usergrid.central.url

        String suToken = clientSetup.getSuperuserToken().getAccessToken();
        Map<String, String> props = new HashMap<String, String>();
        props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm());
        resource().path( "/testproperties" )
                .queryParam( "access_token", suToken)
                .accept( MediaType.APPLICATION_JSON )
                .type( MediaType.APPLICATION_JSON_TYPE )
                .post( props );

        // calls to login as an Admin User must now fail

        try {

            Map<String, Object> loginInfo = new HashMap<String, Object>() {{
                put("username", username );
                put("password", "password");
                put("grant_type", "password");
            }};
            JsonNode accessInfoNode = resource().path("/management/token")
                    .type( MediaType.APPLICATION_JSON_TYPE )
                    .post( JsonNode.class, loginInfo );
            fail("Login as Admin User must fail when validate external tokens is enabled");

        } catch ( UniformInterfaceException actual ) {
            assertEquals( 400, actual.getResponse().getStatus() );
            String errorMsg = actual.getResponse().getEntity( JsonNode.class ).get( "error_description" ).toString();
            logger.error( "ERROR: " + errorMsg );
            assertTrue( errorMsg.contains( "Admin Users must login via" ));

        } catch ( Exception e ) {
            fail( "We expected a UniformInterfaceException" );
        }

        // login as superuser must succeed

        Map<String, Object> loginInfo = new HashMap<String, Object>() {{
            put("username", "superuser");
            put("password", "superpassword");
            put("grant_type", "password");
        }};
        JsonNode accessInfoNode = resource().path("/management/token")
                .type( MediaType.APPLICATION_JSON_TYPE )
                .post( JsonNode.class, loginInfo );
        String accessToken = accessInfoNode.get( "access_token" ).textValue();
        assertNotNull( accessToken );

        // turn off validate external tokens by un-setting the usergrid.central.url

        props.put( USERGRID_CENTRAL_URL, "" );
        resource().path( "/testproperties" )
                .queryParam( "access_token", suToken)
                .accept( MediaType.APPLICATION_JSON )
                .type( MediaType.APPLICATION_JSON_TYPE )
                .post( props );
    }

}
