package org.exoplatform.cs.rest;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.exoplatform.cs.dto.EnvironmentDTO;
import org.exoplatform.cs.dto.SpaceDTO;
import org.exoplatform.cs.rest.model.CSEnvironment;
import org.exoplatform.cs.rest.model.CSUserSettings;
import org.exoplatform.cs.rest.utils.CSRestUtils;
import org.exoplatform.cs.rest.utils.EntityBuilder;
import org.exoplatform.cs.service.CSSpaceService;
import org.exoplatform.cs.service.EnvironmentService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.rest.resource.ResourceContainer;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;


@Path("/customer-space/space")
@Tag(name = "/customer-space/space", description = "Manages customer space information")
public class CustomerSpaceRest implements ResourceContainer {
    private CSSpaceService csSpaceService;
    private EnvironmentService environmentService;

    private static final String SPACE_GROUP = "/spaces/";
    private static final Log LOG = ExoLogger.getLogger(CustomerSpaceRest.class);


    public CustomerSpaceRest (CSSpaceService csSpaceService, EnvironmentService environmentService) {
        this.csSpaceService = csSpaceService;
        this.environmentService = environmentService;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/environment/{id}")
    @RolesAllowed("users")
    @Operation(
            description = "retrieves a space environment")
    @ApiResponses(
            value = {@ApiResponse(responseCode = "200", description = "Request fulfilled"),
                    @ApiResponse(responseCode = "401", description = "Unauthorized operation"),
                    @ApiResponse(responseCode = "500", description = "Internal server error"),}
    )
    public Response getEnvironmentById(@Parameter(description = "space environment id", required = true) @PathParam("id") Long id) {
        EnvironmentDTO environmentDTO = null;
        try {
            if (id != null) {
                environmentDTO = environmentService.getEnvironment(id);
            }
            if (environmentDTO == null) {
                return Response.status(Response.Status.NOT_FOUND).entity("No saved environment was found").build();
            }

            if (!CSRestUtils.authorizedOnCS(environmentDTO.getSpaceGroupId())) {
                return Response.status(Response.Status.UNAUTHORIZED).entity("Your are not authorized").build();
            }
        } catch (Exception e) {
            LOG.error("Error while retrieving saved customer space environment", e);
            return Response.serverError().entity(e.getMessage()).build();
        }
        return Response.ok(EntityBuilder.fromEnvironmentDto(environmentDTO)).build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/environments")
    @RolesAllowed("users")
    @Operation(
            description = "retrieves all space environments",
            method = "GET"
    )
    @ApiResponses(
            value = {@ApiResponse(responseCode = "200", description = "Request fulfilled"),
                    @ApiResponse(responseCode = "401", description = "Unauthorized operation"),
                    @ApiResponse(responseCode = "500", description = "Internal server error"),}
    )
    public Response getEnvironmentsBySpaceGroupId(@Parameter(description = "customer space group id", required = true)
                                                      @QueryParam("groupId") String groupId) {
        List<EnvironmentDTO> environmentsDto = null;
        if (groupId == null) {
            return Response.status(Response.Status.NOT_FOUND).entity("space id is mandatory").build();
        }

        if (!CSRestUtils.authorizedOnCS(SPACE_GROUP + groupId)) {
            return Response.status(Response.Status.UNAUTHORIZED).entity("Your are not authorized").build();
        }
        try {
            if (groupId != null) {
                environmentsDto = environmentService.getSpaceEnvironments(SPACE_GROUP + groupId);
            }
            if (environmentsDto == null) {
                return Response.status(Response.Status.NOT_FOUND).entity("No saved environments was found").build();
            }

        } catch (Exception e) {
            LOG.error("Error while retrieving saved customer space environments", e);
            return Response.serverError().entity(e.getMessage()).build();
        }
        List<CSEnvironment> environments = new ArrayList<>();
        environmentsDto.stream().forEach(envDto -> environments.add(EntityBuilder.fromEnvironmentDto(envDto)));

        return Response.ok(environments).build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/settings")
    @RolesAllowed("users")
    @Operation(
            description = "retrieves the customer space current user settings",
            method = "GET"
    )
    @ApiResponses(
            value = {@ApiResponse(responseCode = "200", description = "Request fulfilled"),
                    @ApiResponse(responseCode = "401", description = "Unauthorized operation"),
                    @ApiResponse(responseCode = "500", description = "Internal server error"),}
    )
    public Response getCSUserSettings() {
        CSUserSettings csUserSettings = new CSUserSettings();
        try {
            User user = CSRestUtils.getCurrentUser();
            csUserSettings.setUserName(user.getUserName());
            csUserSettings.setFullName(user.getDisplayName());
            csUserSettings.setSupport(CSRestUtils.isSupportMember());
            csUserSettings.setCanManage(CSRestUtils.canManage());
            csUserSettings.setAvatarUrl(CSRestUtils.getProfile(user.getUserName()).getAvatarUrl());
        } catch (Exception e) {
            LOG.error("Error while getting customer space current user settings", e);
            return Response.serverError().entity(e.getMessage()).build();
        }
        return Response.ok(csUserSettings).build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{groupId}")
    @RolesAllowed("users")
    @Operation(
            description = "retrieves the customer space information",
            method = "GET"
    )
    @ApiResponses(
            value = {@ApiResponse(responseCode = "200", description = "Request fulfilled"),
                    @ApiResponse(responseCode = "401", description = "Unauthorized operation"),
                    @ApiResponse(responseCode = "500", description = "Internal server error"),}
    )
    public Response getSpaceByGroupId(@Parameter(description = "space group id", required = true) @PathParam("groupId") String groupId) {
        SpaceDTO spaceDTO = null;
        if (groupId == null) {
            return Response.status(Response.Status.NOT_FOUND).entity("space id is mandatory").build();
        }

        if (!CSRestUtils.authorizedOnCS(SPACE_GROUP + groupId)) {
            return Response.status(Response.Status.UNAUTHORIZED).entity("Your are not authorized").build();
        }

        try {
            spaceDTO = csSpaceService.getSpace(SPACE_GROUP + groupId);
        } catch (Exception e) {
            LOG.error("Error while getting customer space information", e);
            return Response.serverError().entity(e.getMessage()).build();
        }
        if (spaceDTO == null) {
            return Response.status(Response.Status.NOT_FOUND).entity("ticket not found").build();
        }
        return Response.ok(CSRestUtils.extendCSSpace(EntityBuilder.fromSpaceDto(spaceDTO))).build();
    }

}
