/*
 * Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
 *
 * 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.
 */

package org.etsi.tfs.policy;

import static org.assertj.core.api.Assertions.assertThat;
import static org.etsi.tfs.policy.common.ApplicationProperties.REMOVED_POLICYRULE_STATE;

import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectMock;
import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.etsi.tfs.policy.context.ContextService;
import org.etsi.tfs.policy.context.model.Service;
import org.etsi.tfs.policy.context.model.ServiceId;
import org.etsi.tfs.policy.context.model.ServiceTypeEnum;
import org.etsi.tfs.policy.monitoring.MonitoringService;
import org.etsi.tfs.policy.monitoring.model.IntegerKpiValue;
import org.etsi.tfs.policy.monitoring.model.KpiValue;
import org.etsi.tfs.policy.policy.PolicyServiceImpl;
import org.etsi.tfs.policy.policy.model.BooleanOperator;
import org.etsi.tfs.policy.policy.model.NumericalOperator;
import org.etsi.tfs.policy.policy.model.PolicyRule;
import org.etsi.tfs.policy.policy.model.PolicyRuleAction;
import org.etsi.tfs.policy.policy.model.PolicyRuleActionConfig;
import org.etsi.tfs.policy.policy.model.PolicyRuleActionEnum;
import org.etsi.tfs.policy.policy.model.PolicyRuleBasic;
import org.etsi.tfs.policy.policy.model.PolicyRuleCondition;
import org.etsi.tfs.policy.policy.model.PolicyRuleService;
import org.etsi.tfs.policy.policy.model.PolicyRuleState;
import org.etsi.tfs.policy.policy.model.PolicyRuleStateEnum;
import org.etsi.tfs.policy.policy.model.PolicyRuleType;
import org.etsi.tfs.policy.policy.model.PolicyRuleTypeService;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

@QuarkusTest
class PolicyDeleteServiceTest {

    @Inject PolicyServiceImpl policyService;
    @InjectMock ContextService contextService;

    @InjectMock MonitoringService monitoringService;

    static PolicyRuleBasic policyRuleBasic;
    static PolicyRuleService policyRuleService;

    @BeforeAll
    static void init() {

        String policyId = "policyRuleId";
        KpiValue kpiValue = new IntegerKpiValue(100);

        PolicyRuleCondition policyRuleCondition =
                new PolicyRuleCondition(
                        "kpiId", NumericalOperator.POLICY_RULE_CONDITION_NUMERICAL_GREATER_THAN, kpiValue);

        PolicyRuleActionConfig policyRuleActionConfig = new PolicyRuleActionConfig("key", "value");

        PolicyRuleAction policyRuleAction =
                new PolicyRuleAction(
                        PolicyRuleActionEnum.POLICY_RULE_ACTION_NO_ACTION,
                        Arrays.asList(policyRuleActionConfig));

        policyRuleBasic =
                new PolicyRuleBasic(
                        policyId,
                        new PolicyRuleState(PolicyRuleStateEnum.POLICY_INSERTED, "Failed due to some errors"),
                        1,
                        Arrays.asList(policyRuleCondition),
                        BooleanOperator.POLICYRULE_CONDITION_BOOLEAN_OR,
                        Arrays.asList(policyRuleAction));

        ServiceId serviceId = new ServiceId("contextId", "serviceId");

        Service service = new Service(serviceId, ServiceTypeEnum.UNKNOWN, null, null, null, null, 0.0);

        List<String> deviceIds = Arrays.asList("device1", "device2");

        policyRuleService = new PolicyRuleService(policyRuleBasic, serviceId, deviceIds);
    }

    @Test
    void contextOrServiceIdMustNotBeEmpty()
            throws ExecutionException, InterruptedException, TimeoutException {
        CompletableFuture<PolicyRuleState> message = new CompletableFuture<>();

        String policyRuleId = "";
        PolicyRuleState expectedResult =
                new PolicyRuleState(
                        PolicyRuleStateEnum.POLICY_REMOVED,
                        REMOVED_POLICYRULE_STATE.getPolicyRuleStateMessage());

        PolicyRuleType policyRuleType = new PolicyRuleTypeService(policyRuleService);

        PolicyRule policyRule = new PolicyRule(policyRuleType);

        Mockito.when(contextService.getPolicyRule(Mockito.anyString()))
                .thenReturn(Uni.createFrom().item(policyRule));

        policyService
                .deletePolicy(policyRuleId)
                .subscribe()
                .with(
                        item -> {
                            message.complete(item);
                        });

        assertThat(message.get(5, TimeUnit.SECONDS).getPolicyRuleStateMessage())
                .isEqualTo(expectedResult.getPolicyRuleStateMessage().toString());
    }
}
