/*
 * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
 *
 * Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.admin;

import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.AuthorizationRequest;
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.ErrorResponse;
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.admin.DeviceAccessAuthorizationAdminService;
import io.entgra.device.mgt.core.device.mgt.api.jaxrs.util.DeviceMgtAPIUtils;
import io.entgra.device.mgt.core.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import io.entgra.device.mgt.core.device.mgt.common.authorization.DeviceAuthorizationResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;

@Path("/admin/authorization")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class DeviceAccessAuthorizationAdminServiceImpl implements DeviceAccessAuthorizationAdminService {

    private static final Log log = LogFactory.getLog(DeviceAccessAuthorizationAdminServiceImpl.class);
    private static final String DEFAULT_STAT_PERMISSION = "/permission/admin/device-mgt/device/realtime_analytics";

    @POST
    @Override
    public Response isAuthorized(AuthorizationRequest authorizationRequest) {
        int currentTenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
        String loggedinUserTenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
        if (authorizationRequest.getTenantDomain() != null) {
            if (!loggedinUserTenantDomain.equals(authorizationRequest.getTenantDomain())) {
                if (MultitenantConstants.SUPER_TENANT_ID != currentTenantId) {
                    return Response.status(Response.Status.UNAUTHORIZED).entity(
                            new ErrorResponse.ErrorResponseBuilder().setMessage(
                                    "Current logged in user is not authorized to perform this operation").build())
                            .build();
                }
            }
        } else {
            authorizationRequest.setTenantDomain(loggedinUserTenantDomain);
        }
        if (authorizationRequest.getTenantDomain() == null || authorizationRequest.getTenantDomain().isEmpty()) {
            authorizationRequest.setTenantDomain(
                    PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain());
        }
        try {
            PrivilegedCarbonContext.startTenantFlow();
            PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
                    authorizationRequest.getTenantDomain(), true);
            String[] permissionArr = null;
            if (authorizationRequest.getPermissions() != null && authorizationRequest.getPermissions().size() > 0) {
                permissionArr = new String[authorizationRequest.getPermissions().size()];
                permissionArr = authorizationRequest.getPermissions().toArray(permissionArr);
            }
            DeviceAuthorizationResult deviceAuthorizationResult =
                    DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
                            authorizationRequest.getDeviceIdentifiers(), authorizationRequest.getUsername()
                            , permissionArr);

            return Response.status(Response.Status.OK).entity(deviceAuthorizationResult).build();
        } catch (DeviceAccessAuthorizationException e) {
            String msg = "Error occurred at server side while fetching authorization information.";
            log.error(msg, e);
            return Response.serverError().entity(
                    new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
        } finally {
            PrivilegedCarbonContext.endTenantFlow();
        }
    }

    @POST
    @Path("/stat")
    @Override
    public Response isAuthorizedForStat(AuthorizationRequest authorizationRequest) {
        List<String> permissions = new ArrayList<>();
        permissions.add(DEFAULT_STAT_PERMISSION);
        authorizationRequest.setPermissions(permissions);
        return isAuthorized(authorizationRequest);
    }

}
