/*-
 * ============LICENSE_START=======================================================
 * OSAM
 * ================================================================================
 * Copyright (C) 2018 AT&T
 * ================================================================================
 * Licensed 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.
 * ============LICENSE_END=========================================================
 */



package org.onap.osam.services;

import com.google.common.collect.ImmutableMap;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.SessionFactory;
import org.onap.osam.aai.AaiClientInterface;
import org.onap.osam.aai.AaiResponse;
import org.onap.osam.aai.exceptions.InvalidAAIResponseException;
import org.onap.osam.aai.model.AaiNodeQueryResponse;
import org.onap.osam.aai.model.ResourceType;
import org.onap.osam.domain.mso.CloudConfiguration;
import org.onap.osam.exceptions.DbFailureUncheckedException;
import org.onap.osam.exceptions.GenericUncheckedException;
import org.onap.osam.exceptions.MaxRetriesException;
import org.onap.osam.exceptions.OperationNotAllowedException;
import org.onap.osam.job.Job;
import org.onap.osam.job.Job.JobStatus;
import org.onap.osam.job.JobAdapter;
import org.onap.osam.job.JobType;
import org.onap.osam.job.JobsBrokerService;
import org.onap.osam.model.JobAuditStatus;
import org.onap.osam.model.NameCounter;
import org.onap.osam.model.ServiceInfo;
import org.onap.osam.model.serviceInstantiation.ServiceInstantiation;
import org.onap.osam.model.serviceInstantiation.VfModule;
import org.onap.osam.model.serviceInstantiation.Vnf;
import org.onap.osam.mso.MsoBusinessLogicImpl;
import org.onap.osam.mso.MsoProperties;
import org.onap.osam.mso.model.ServiceInstantiationRequestDetails;
import org.onap.osam.mso.rest.AsyncRequestStatus;
import org.onap.osam.utils.DaoUtils;
import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
import org.onap.portalsdk.core.service.DataAccessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Service
public class AsyncInstantiationBusinessLogicImpl implements IAsyncInstantiationBusinessLogic {

    private static final int MAX_RETRIES_GETTING_COUNTER = 100;
    private static final int MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI = 10000;
    public static final String NAME_FOR_CHECK_AAI_STATUS = "NAME_FOR_CHECK_AAI_STATUS";

    private final DataAccessService dataAccessService;

    private final JobAdapter jobAdapter;

    private final JobsBrokerService jobService;

    private SessionFactory sessionFactory;

    private AaiClientInterface aaiClient;

    private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI;

    private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class);
    private Map<String, JobStatus> msoStateToJobStatusMap = ImmutableMap.<String, JobStatus>builder()
            .put("inprogress", JobStatus.IN_PROGRESS)
            .put("failed", JobStatus.FAILED)
            .put("pause", JobStatus.PAUSE)
            .put("paused", JobStatus.PAUSE)
            .put("complete", JobStatus.COMPLETED)
            .put("pending", JobStatus.IN_PROGRESS)
            .put("pendingmanualtask", JobStatus.PAUSE)
            .put("unlocked", JobStatus.IN_PROGRESS)
            .build();


    @Autowired
    public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService,
                                               JobAdapter jobAdapter,
                                               JobsBrokerService jobService,
                                               SessionFactory sessionFactory,
                                               AaiClientInterface aaiClient) {
        this.dataAccessService = dataAccessService;
        this.jobAdapter = jobAdapter;
        this.jobService = jobService;
        this.sessionFactory = sessionFactory;
        this.aaiClient = aaiClient;
    }

    @Override
    public List<ServiceInfo> getAllServicesInfo() {
        return dataAccessService.getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null);
    }

    private String filterByCreationDateAndNotDeleted() {
        LocalDateTime minus3Months = LocalDateTime.now().minusMonths(3);
        Timestamp filterDate = Timestamp.valueOf(minus3Months);
        return " where" +
                "   hidden = false" +
                "   and deleted_at is null" +  // don't fetch deleted
                "   and created >= '" + filterDate + "' ";
    }

    private String orderByCreatedDateAndStatus() {
        return " createdBulkDate DESC ,\n" +
                "  (CASE jobStatus\n" +
                "   WHEN 'COMPLETED' THEN 0\n" +
                "   WHEN 'FAILED' THEN 0\n" +
                "   WHEN 'IN_PROGRESS' THEN 1\n" +
                "   WHEN 'PAUSE' THEN 2\n" +
                "   WHEN 'PENDING' THEN 3\n" +
                "   WHEN 'STOPPED' THEN 3 END),\n" +
                "  statusModifiedDate ";
    }

    @Override
    public List<UUID> pushBulkJob(ServiceInstantiation request, String userId) {
        List<UUID> uuids = new ArrayList<>();
        Date createdBulkDate = Calendar.getInstance().getTime();
        int bulkSize = request.getBulkSize();
        UUID templateId = UUID.randomUUID();
        for (int i = 0; i < bulkSize; i++) {
            //Job job = jobAdapter.createJob(JobType.ServiceInstantiation, request, templateId, userId, i);
            Job job = jobAdapter.createJob(JobType.NoOp, request, templateId, userId, i);//should be some instatiation, this was changed as part of code cleaning

            UUID jobId = jobService.add(job);
            auditVidStatus(jobId,job.getStatus());
            uuids.add(jobId);
            dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate), DaoUtils.getPropsMap());
        }
        return uuids;
    }

    private ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate) {
        return new ServiceInfo(
                userId, Job.JobStatus.PENDING, serviceInstantiation.isPause(), jobId, templateId,
                serviceInstantiation.getOwningEntityId(),
                serviceInstantiation.getOwningEntityName(),
                serviceInstantiation.getProjectName(),
                serviceInstantiation.getAicZoneId(),
                serviceInstantiation.getAicZoneName(),
                serviceInstantiation.getTenantId(),
                serviceInstantiation.getTenantName(),
                serviceInstantiation.getLcpCloudRegionId(),
                null,
                serviceInstantiation.getSubscriptionServiceType(),
                serviceInstantiation.getSubscriberName(),
                null,
                serviceInstantiation.getInstanceName(),
                serviceInstantiation.getModelInfo().getModelInvariantId(),
                serviceInstantiation.getModelInfo().getModelName(),
                serviceInstantiation.getModelInfo().getModelVersion(),
                createdBulkDate
        );
    }


    /*//@Override
    public RequestDetailsWrapper<ServiceInstantiationRequestDetails> generateServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String userId) {

           ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.getOwningEntityId(), payload.getOwningEntityName());

        SubscriberInfo subscriberInfo = new SubscriberInfo();
        subscriberInfo.setGlobalSubscriberId(payload.getGlobalSubscriberId());

        String serviceInstanceName = null;
        if(payload.isUserProvidedNaming()) {
            serviceInstanceName = getUniqueName(payload.getInstanceName(), ResourceType.SERVICE_INSTANCE);
            String finalServiceInstanceName = serviceInstanceName;
            updateServiceInfo(jobId, x -> x.setServiceInstanceName(finalServiceInstanceName));
        }
        ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo(
                serviceInstanceName,
                payload.getProductFamilyId(),
                "VID",
                payload.isRollbackOnFailure(),
                userId);

        List<ServiceInstantiationRequestDetails.ServiceInstantiationService> serviceInstantiationService = new LinkedList<>();
        List<Map<String, String>> unFilteredInstanceParams = payload.getInstanceParams() != null ? payload.getInstanceParams() : new LinkedList<>();
        List<Map<String, String>> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams);
        ServiceInstantiationRequestDetails.ServiceInstantiationService serviceInstantiationService1 = new ServiceInstantiationRequestDetails.ServiceInstantiationService(
                payload.getModelInfo(),
                serviceInstanceName,
                filteredInstanceParams,
                createServiceInstantiationVnfList(payload)
        );
        serviceInstantiationService.add(serviceInstantiationService1);

        ServiceInstantiationRequestDetails.RequestParameters requestParameters = new ServiceInstantiationRequestDetails.RequestParameters(payload.getSubscriptionServiceType(), false, serviceInstantiationService);

        ServiceInstantiationRequestDetails.Project project = payload.getProjectName() != null ?  new ServiceInstantiationRequestDetails.Project(payload.getProjectName()) : null;

        ServiceInstantiationRequestDetails requestDetails = new ServiceInstantiationRequestDetails(payload.getModelInfo(), owningEntity, subscriberInfo,
                project, requestInfo, requestParameters);

        RequestDetailsWrapper<ServiceInstantiationRequestDetails> requestDetailsWrapper = new RequestDetailsWrapper(requestDetails);
        debugRequestDetails(requestDetailsWrapper, logger);
        return requestDetailsWrapper;
    }*/

    private List<Map<String, String>> removeUnNeededParams(List<Map<String, String>> instanceParams) {
        List<String> keysToRemove = new ArrayList<>();
        if (instanceParams != null && !instanceParams.isEmpty()) {
            for (String key : instanceParams.get(0).keySet()) {
                for (String paramToIgnore : PARAMS_TO_IGNORE)
                    if ((key.equalsIgnoreCase(paramToIgnore))) {
                        keysToRemove.add(key);
                    }
            }
            for (String key : keysToRemove) {
                instanceParams.get(0).remove(key);
            }
            //TODO will be removed on once we stop using List<Map<String, String>>
            if (instanceParams.get(0).isEmpty()) {
                return Collections.emptyList();
            }
        }
        return instanceParams;
    }

    private ServiceInstantiationRequestDetails.ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) {
        CloudConfiguration cloudConfiguration = new CloudConfiguration();
        cloudConfiguration.setTenantId(payload.getTenantId());
        cloudConfiguration.setLcpCloudRegionId(payload.getLcpCloudRegionId());

        Map<String, Vnf> vnfs = payload.getVnfs();
        List<ServiceInstantiationRequestDetails.ServiceInstantiationVnf> vnfList = new ArrayList<>();
        for (Vnf vnf : vnfs.values()) {
            Map<String, Map<String, VfModule>> vfModules = vnf.getVfModules();
            List<VfModule> convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules);
            List<VfModule> filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules, vnf.isUserProvidedNaming());
            ServiceInstantiationRequestDetails.ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationRequestDetails.ServiceInstantiationVnf(
                    vnf.getModelInfo(),
                    cloudConfiguration,
                    vnf.getPlatformName(),
                    vnf.getLineOfBusiness(),
                    payload.getProductFamilyId(),
                    removeUnNeededParams(vnf.getInstanceParams()),
                    filteredVfModules,
                    vnf.isUserProvidedNaming() ? getUniqueName(vnf.getInstanceName(), ResourceType.GENERIC_VNF) : null
            );
            vnfList.add(serviceInstantiationVnf);
        }

        return new ServiceInstantiationRequestDetails.ServiceInstantiationVnfList(vnfList);
    }

    private List<VfModule> convertVfModuleMapToList(Map<String, Map<String, VfModule>> vfModules) {
        return vfModules.values().stream().flatMap(vfModule -> vfModule.values().stream()).collect(Collectors.toList());
    }

    private List<VfModule> filterInstanceParamsFromVfModuleAndUniqueNames(List<VfModule> unFilteredVfModules, boolean isUserProvidedNaming) {
        return unFilteredVfModules.stream().map(vfModule ->
                new VfModule(
                        vfModule.getModelInfo(),
                        getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getInstanceName(), ResourceType.VF_MODULE),
                        getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP),
                        removeUnNeededParams(vfModule.getInstanceParams())))
                .collect(Collectors.toList());
    }

    private String getUniqueNameIfNeeded(boolean isUserProvidedNaming, String name, ResourceType resourceType) {
        return isUserProvidedNaming && !StringUtils.isEmpty(name) ?
                getUniqueName(name, resourceType) : null;
    }

    @Override
    public String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest) {
        //in case pause flag is true - use assign , else - use create.
        return MsoBusinessLogicImpl.validateEndpointPath(
                serviceInstantiationRequest.isPause() ?
                        "mso.restapi.serviceInstanceAssign" : "mso.restapi.serviceInstanceCreate"
        );
    }

    @Override
    public String getOrchestrationRequestsPath() {
        return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ);
    }

    @Override
    public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer<ServiceInfo> serviceUpdater) {
        ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
        serviceUpdater.accept(serviceInfo);
        dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
        return serviceInfo;
    }

    @Override
    public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) {
        auditVidStatus(jobUuid,jobStatus);
        return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus));
    }

    private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) {
        serviceInfo.setJobStatus(jobStatus);
        serviceInfo.setStatusModifiedDate(new Date());
    }

    public ServiceInfo getServiceInfoByJobId(UUID jobUUID) {
        List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null);
        if (serviceInfoList.size() != 1) {
            throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size());
        }
        return serviceInfoList.get(0);
    }

    public List<JobAuditStatus> getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) {
        return dataAccessService.getList(
            JobAuditStatus.class,
            String.format(" where SOURCE = '%s' and JOB_ID = '%s'",source, jobUUID),
            " CREATED_DATE ", null);
    }

    private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){
        List<JobAuditStatus> list = getAuditStatuses(jobUUID,source);
        return !list.isEmpty() ? list.get(list.size()-1) : null;
    }

    @Override
    public void auditVidStatus(UUID jobUUID, JobStatus jobStatus){
        JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID);
        auditStatus(vidStatus);
    }

    @Override
    public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){
        auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage());
    }

    @Override
    public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){
        JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO,
                requestId != null ? UUID.fromString(requestId) : null,
                additionalInfo);
        auditStatus(msoStatus);
    }

    private void auditStatus(JobAuditStatus jobAuditStatus){
        JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(),jobAuditStatus.getSource());
        if (latestStatus == null || !latestStatus.equals(jobAuditStatus))
            dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap());

    }

    public Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus) {
        String msoRequestState = asyncRequestStatus.request.requestStatus.getRequestState().toLowerCase().replaceAll("[^a-z]+", "");
        JobStatus jobStatus = msoStateToJobStatusMap.get(msoRequestState);
        return (jobStatus != null ? jobStatus : JobStatus.IN_PROGRESS);
    }

    @Override
    public void handleFailedInstantiation(UUID jobUUID) {
        ServiceInfo serviceInfo = updateServiceInfoAndAuditStatus(jobUUID, JobStatus.FAILED);
        List<ServiceInfo> serviceInfoList = dataAccessService.getList(
                ServiceInfo.class,
                String.format(" where templateId = '%s' and jobStatus = '%s'",
                        serviceInfo.getTemplateId(),
                        JobStatus.PENDING),
                null, null);
        serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED));
    }

    @Override
    public void deleteJob(UUID jobId) {
        jobService.delete(jobId);
        Date now = new Date();
        updateServiceInfo(jobId, x -> x.setDeletedAt(now));
    }

    @Override
    public void hideServiceInfo(UUID jobUUID) {
        ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
        if (!serviceInfo.getJobStatus().isFinal()) {
            String message = String.format( "jobId %s: Service status does not allow hide service, status = %s",
                    serviceInfo.getJobId(),
                    serviceInfo.getJobStatus());
            logger.error(EELFLoggerDelegate.errorLogger, message);
            throw new OperationNotAllowedException(message);
        }
        serviceInfo.setHidden(true);
        dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
    }

    @Override
    public int


    getCounterForName(String name) {

        String hqlSelectNC = "from NameCounter where name = :name";
        String hqlUpdateCounter = "update NameCounter set counter = :newCounter " +
                "where name= :name " +
                "and counter= :prevCounter";

        Integer counter = null;
        GenericUncheckedException lastException = null;
        for (int i = 0; i< MAX_RETRIES_GETTING_COUNTER && counter==null; i++) {
            try {
                counter = calcCounter(name, hqlSelectNC, hqlUpdateCounter);
            }
            catch (GenericUncheckedException exception) {
                lastException = exception; //do nothing, we will try again in the loop
            }
        }

        if (counter!=null) {
            return counter;
        }

        throw lastException!=null ? new DbFailureUncheckedException(lastException) :
                new DbFailureUncheckedException("Failed to get counter for "+name+" due to unknown error");

    }

    private Integer calcCounter(String name, String hqlSelectNC, String hqlUpdateCounter) {
        Integer counter;
        counter = DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> {
            NameCounter nameCounter = (NameCounter) session.createQuery(hqlSelectNC)
                    .setText("name", name)
                    .uniqueResult();
            if (nameCounter != null) {
                int updatedRows = session.createQuery(hqlUpdateCounter)
                        .setText("name", nameCounter.getName())
                        .setInteger("prevCounter", nameCounter.getCounter())
                        .setInteger("newCounter", nameCounter.getCounter() + 1)
                        .executeUpdate();
                if (updatedRows == 1) {
                    return nameCounter.getCounter() + 1;
                }
            } else {
                Object nameAsId = session.save(new NameCounter(name));
                //if save success
                if (nameAsId != null) {
                    return 1;
                }
            }
            //in case of failure return null, in order to continue the loop
            return null;
        });
        return counter;
    }

    @Override
    public int getMaxRetriesGettingFreeNameFromAai() {
        return maxRetriesGettingFreeNameFromAai;
    }

    @Override
    public void setMaxRetriesGettingFreeNameFromAai(int maxRetriesGettingFreeNameFromAai) {
        this.maxRetriesGettingFreeNameFromAai = maxRetriesGettingFreeNameFromAai;
    }

    @Override
    public String getUniqueName(String name, ResourceType resourceType) {
        //check that name aai response well before increasing counter from DB
        //Prevents unnecessary increasing of the counter while AAI doesn't response
        isNameFreeInAai(NAME_FOR_CHECK_AAI_STATUS, resourceType);

        for (int i=0; i<getMaxRetriesGettingFreeNameFromAai(); i++) {
            int counter = getCounterForName(name);
            String newName = formatNameAndCounter(name, counter);
            if (isNameFreeInAai(newName, resourceType)) {
                return newName;
            }
        }

        throw new MaxRetriesException("find unused name for "+name, getMaxRetriesGettingFreeNameFromAai());
    }

    //the method is protected so we can call it in the UT
    protected String formatNameAndCounter(String name, int counter) {
        return name + "_" + String.format("%03d", counter);
    }

    private boolean isNameFreeInAai(String name, ResourceType resourceType) throws InvalidAAIResponseException {
        AaiResponse<AaiNodeQueryResponse> aaiResponse = aaiClient.searchNodeTypeByName(name, resourceType);
        if (aaiResponse.getHttpCode() > 399 || aaiResponse.getT() == null) {
            throw new InvalidAAIResponseException(aaiResponse);
        }
        return CollectionUtils.isEmpty(aaiResponse.getT().resultData);
    }

}
