/*
 * 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.servicecomb.pack.alpha.server.api;

import static org.hamcrest.Matchers.hasSize;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.servicecomb.pack.alpha.core.NodeStatus;
import org.apache.servicecomb.pack.alpha.core.NodeStatus.TypeEnum;
import org.apache.servicecomb.pack.alpha.fsm.SagaActorState;
import org.apache.servicecomb.pack.alpha.core.fsm.TransactionType;
import org.apache.servicecomb.pack.alpha.core.fsm.TxState;
import org.apache.servicecomb.pack.alpha.core.fsm.event.SagaEndedEvent;
import org.apache.servicecomb.pack.alpha.core.fsm.event.SagaStartedEvent;
import org.apache.servicecomb.pack.alpha.core.fsm.event.TxEndedEvent;
import org.apache.servicecomb.pack.alpha.core.fsm.event.TxStartedEvent;
import org.apache.servicecomb.pack.alpha.core.fsm.event.base.BaseEvent;
import org.apache.servicecomb.pack.alpha.core.metrics.MetricsBean;
import org.apache.servicecomb.pack.alpha.fsm.metrics.MetricsService;
import org.apache.servicecomb.pack.alpha.fsm.repository.TransactionRepository;
import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.GlobalTransaction;
import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.PagingGlobalTransactions;
import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.SagaSubTransaction;
import org.apache.servicecomb.pack.alpha.server.AlphaApplication;
import org.apache.servicecomb.pack.alpha.server.AlphaConfig;
import org.apache.servicecomb.pack.alpha.server.metrics.AlphaMetricsEndpoint;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest(classes = {AlphaApplication.class, AlphaConfig.class})
public class APIv1ControllerTest {

  @Autowired
  private MockMvc mockMvc;

  @Autowired
  AlphaMetricsEndpoint alphaMetricsEndpoint;

  @MockBean
  MetricsService metricsService;

  @MockBean
  NodeStatus nodeStatus;

  @MockBean
  ElasticsearchTemplate template;

  @MockBean
  TransactionRepository transactionRepository;

  @Test
  public void metricsTest() throws Exception {
    MetricsBean metricsBean = new MetricsBean();
    metricsBean.doEventReceived();
    metricsBean.doEventAccepted();
    metricsBean.doEventAvgTime(5);
    metricsBean.doActorReceived();
    metricsBean.doActorAccepted();
    metricsBean.doActorAvgTime(5);
    metricsBean.doRepositoryReceived();
    metricsBean.doRepositoryAccepted();
    metricsBean.doRepositoryAvgTime(5);
    metricsBean.doCommitted();
    metricsBean.doCompensated();
    metricsBean.doSuspended();
    metricsBean.doSagaBeginCounter();
    metricsBean.doSagaEndCounter();
    metricsBean.doSagaAvgTime(5);
    when(metricsService.metrics()).thenReturn(metricsBean);
    when(nodeStatus.getTypeEnum()).thenReturn(TypeEnum.MASTER);
    mockMvc.perform(get("/alpha/api/v1/metrics"))
        .andExpect(status().isOk())
        .andExpect(
            MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(jsonPath("$.metrics.eventReceived").value(1))
        .andExpect(jsonPath("$.metrics.eventAccepted").value(1))
        .andExpect(jsonPath("$.metrics.eventRejected").value(0))
        .andExpect(jsonPath("$.metrics.eventAvgTime").value(5.0))
        .andExpect(jsonPath("$.metrics.actorReceived").value(1))
        .andExpect(jsonPath("$.metrics.actorAccepted").value(1))
        .andExpect(jsonPath("$.metrics.actorRejected").value(0))
        .andExpect(jsonPath("$.metrics.actorAvgTime").value(5.0))
        .andExpect(jsonPath("$.metrics.repositoryReceived").value(1))
        .andExpect(jsonPath("$.metrics.repositoryAccepted").value(1))
        .andExpect(jsonPath("$.metrics.repositoryRejected").value(0))
        .andExpect(jsonPath("$.metrics.repositoryAvgTime").value(5.0))
        .andExpect(jsonPath("$.metrics.sagaBeginCounter").value(1))
        .andExpect(jsonPath("$.metrics.sagaEndCounter").value(1))
        .andExpect(jsonPath("$.metrics.sagaAvgTime").value(5.0))
        .andExpect(jsonPath("$.metrics.committed").value(1))
        .andExpect(jsonPath("$.metrics.compensated").value(1))
        .andExpect(jsonPath("$.metrics.suspended").value(1))
        .andExpect(jsonPath("$.nodeType").value(TypeEnum.MASTER.name()))
        .andReturn();
  }

  @Test
  public void transactionTest() throws Exception {
    final String serviceName = "serviceName-1";
    final String instanceId = "instanceId-1";
    final String globalTxId = UUID.randomUUID().toString();
    final String localTxId_1 = UUID.randomUUID().toString();
    final String localTxId_2 = UUID.randomUUID().toString();
    final String localTxId_3 = UUID.randomUUID().toString();

    List<BaseEvent> events = new ArrayList();
    events.add(SagaStartedEvent.builder().serviceName("service_g").instanceId("instance_g")
        .globalTxId(globalTxId).build());
    events.add(TxStartedEvent.builder().serviceName("service_c1").instanceId("instance_c1")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_1).build());
    events.add(TxEndedEvent.builder().serviceName("service_c1").instanceId("instance_c1")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_1).build());
    events.add(TxStartedEvent.builder().serviceName("service_c2").instanceId("instance_c2")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_2).build());
    events.add(TxEndedEvent.builder().serviceName("service_c2").instanceId("instance_c2")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_2).build());
    events.add(TxStartedEvent.builder().serviceName("service_c3").instanceId("instance_c3")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_3).build());
    events.add(TxEndedEvent.builder().serviceName("service_c3").instanceId("instance_c3")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_3).build());
    events.add(SagaEndedEvent.builder().serviceName("service_g").instanceId("instance_g")
        .globalTxId(globalTxId).build());

    List<SagaSubTransaction> subTransactions = new ArrayList();
    subTransactions
        .add(SagaSubTransaction.builder().parentTxId(globalTxId).localTxId(localTxId_1).state(
            TxState.COMMITTED).beginTime(new Date()).endTime(new Date()).build());
    subTransactions
        .add(SagaSubTransaction.builder().parentTxId(globalTxId).localTxId(localTxId_2).state(
            TxState.COMMITTED).beginTime(new Date()).endTime(new Date()).build());
    subTransactions
        .add(SagaSubTransaction.builder().parentTxId(globalTxId).localTxId(localTxId_3).state(
            TxState.COMMITTED).beginTime(new Date()).endTime(new Date()).build());

    List<GlobalTransaction> globalTransactions = new ArrayList<>();
    globalTransactions.add(GlobalTransaction.builder()
        .serviceName(serviceName)
        .instanceId(instanceId)
        .globalTxId(globalTxId)
        .type(TransactionType.SAGA)
        .state(SagaActorState.COMMITTED.name())
        .beginTime(new Date())
        .endTime(new Date())
        .subTxSize(3)
        .events(events)
        .subTransactions(subTransactions)
        .build());
    PagingGlobalTransactions paging = PagingGlobalTransactions.builder()
        .page(0)
        .size(50)
        .elapsed(10)
        .total(1)
        .globalTransactions(globalTransactions)
        .build();

    when(transactionRepository.getGlobalTransactions(null,0, 50)).thenReturn(paging);

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
    mapper.configure(Feature.QUOTE_NON_NUMERIC_NUMBERS, false);
    mockMvc.perform(get("/alpha/api/v1/transaction?page=0&size=50"))
        .andExpect(status().isOk())
        .andExpect(
            MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(jsonPath("$.total").value(1))
        .andExpect(jsonPath("$.page").value(0))
        .andExpect(jsonPath("$.size").value(50))
        .andExpect(jsonPath("$.elapsed").value(10))
        .andExpect(jsonPath("$.globalTransactions", hasSize(1)))
        .andExpect(jsonPath("$.globalTransactions[0].globalTxId")
            .value(globalTransactions.get(0).getGlobalTxId()))
        .andExpect(jsonPath("$.globalTransactions[0].type")
            .value(globalTransactions.get(0).getType().name()))
        .andExpect(jsonPath("$.globalTransactions[0].serviceName")
            .value(globalTransactions.get(0).getServiceName()))
        .andExpect(jsonPath("$.globalTransactions[0].instanceId")
            .value(globalTransactions.get(0).getInstanceId()))
        .andExpect(jsonPath("$.globalTransactions[0].beginTime")
            .value(globalTransactions.get(0).getBeginTime().getTime()))
        .andExpect(jsonPath("$.globalTransactions[0].endTime")
            .value(globalTransactions.get(0).getEndTime().getTime()))
        .andExpect(jsonPath("$.globalTransactions[0].state")
            .value(globalTransactions.get(0).getState()))
        .andExpect(jsonPath("$.globalTransactions[0].subTxSize")
            .value(globalTransactions.get(0).getSubTxSize()))
        .andExpect(jsonPath("$.globalTransactions[0].durationTime")
            .value(globalTransactions.get(0).getDurationTime()))
        .andExpect(jsonPath("$.globalTransactions[0].subTransactions", hasSize(3)))
        .andExpect(jsonPath("$.globalTransactions[0].events", hasSize(8)))
        .andReturn();
  }

  @Test
  public void globalTransactionByGlobalTxIdTest() throws Exception {
    final String serviceName = "serviceName-1";
    final String instanceId = "instanceId-1";
    final String globalTxId = UUID.randomUUID().toString();
    final String localTxId_1 = UUID.randomUUID().toString();
    final String localTxId_2 = UUID.randomUUID().toString();
    final String localTxId_3 = UUID.randomUUID().toString();

    List<BaseEvent> events = new ArrayList();
    events.add(SagaStartedEvent.builder().serviceName("service_g").instanceId("instance_g")
        .globalTxId(globalTxId).build());
    events.add(TxStartedEvent.builder().serviceName("service_c1").instanceId("instance_c1")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_1).build());
    events.add(TxEndedEvent.builder().serviceName("service_c1").instanceId("instance_c1")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_1).build());
    events.add(TxStartedEvent.builder().serviceName("service_c2").instanceId("instance_c2")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_2).build());
    events.add(TxEndedEvent.builder().serviceName("service_c2").instanceId("instance_c2")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_2).build());
    events.add(TxStartedEvent.builder().serviceName("service_c3").instanceId("instance_c3")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_3).build());
    events.add(TxEndedEvent.builder().serviceName("service_c3").instanceId("instance_c3")
        .globalTxId(globalTxId).parentTxId(globalTxId).localTxId(localTxId_3).build());
    events.add(SagaEndedEvent.builder().serviceName("service_g").instanceId("instance_g")
        .globalTxId(globalTxId).build());

    List<SagaSubTransaction> subTransactions = new ArrayList();
    subTransactions
        .add(SagaSubTransaction.builder().parentTxId(globalTxId).localTxId(localTxId_1).state(
            TxState.COMMITTED).beginTime(new Date()).endTime(new Date()).build());
    subTransactions
        .add(SagaSubTransaction.builder().parentTxId(globalTxId).localTxId(localTxId_2).state(
            TxState.COMMITTED).beginTime(new Date()).endTime(new Date()).build());
    subTransactions
        .add(SagaSubTransaction.builder().parentTxId(globalTxId).localTxId(localTxId_3).state(
            TxState.COMMITTED).beginTime(new Date()).endTime(new Date()).build());

    GlobalTransaction globalTransaction = GlobalTransaction.builder()
        .serviceName(serviceName)
        .instanceId(instanceId)
        .globalTxId(globalTxId)
        .type(TransactionType.SAGA)
        .state(SagaActorState.COMMITTED.name())
        .beginTime(new Date())
        .endTime(new Date())
        .subTxSize(3)
        .events(events)
        .subTransactions(subTransactions)
        .build();

    when(transactionRepository.getGlobalTransactionByGlobalTxId(globalTxId)).thenReturn(globalTransaction);

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
    mapper.configure(Feature.QUOTE_NON_NUMERIC_NUMBERS, false);
    mockMvc.perform(get("/alpha/api/v1/transaction/"+globalTxId))
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(
            MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(jsonPath("$.globalTxId")
            .value(globalTransaction.getGlobalTxId()))
        .andExpect(jsonPath("$.type")
            .value(globalTransaction.getType().name()))
        .andExpect(jsonPath("$.serviceName")
            .value(globalTransaction.getServiceName()))
        .andExpect(jsonPath("$.instanceId")
            .value(globalTransaction.getInstanceId()))
        .andExpect(jsonPath("$.beginTime")
            .value(globalTransaction.getBeginTime().getTime()))
        .andExpect(jsonPath("$.endTime")
            .value(globalTransaction.getEndTime().getTime()))
        .andExpect(jsonPath("$.state")
            .value(globalTransaction.getState()))
        .andExpect(jsonPath("$.subTxSize")
            .value(globalTransaction.getSubTxSize()))
        .andExpect(jsonPath("$.durationTime")
            .value(globalTransaction.getDurationTime()))
        .andExpect(jsonPath("$.subTransactions", hasSize(3)))
        .andExpect(jsonPath("$.events", hasSize(8)))
        .andReturn();
  }

  @Test
  public void transactionStatisticsTest() throws Exception {
    Map<String, Long> statistics = new HashMap<>();
    statistics.put("COMMITTED", 1l);
    statistics.put("SUSPENDED", 2l);
    statistics.put("COMPENSATED", 3l);
    when(transactionRepository.getTransactionStatistics()).thenReturn(statistics);
    mockMvc.perform(get("/alpha/api/v1/transaction/statistics"))
        .andExpect(status().isOk())
        .andExpect(
            MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(jsonPath("$.COMMITTED").value(statistics.get("COMMITTED")))
        .andExpect(jsonPath("$.SUSPENDED").value(statistics.get("SUSPENDED")))
        .andExpect(jsonPath("$.COMPENSATED").value(statistics.get("COMPENSATED")))
        .andReturn();
  }

  @Test
  public void transactionSlowTest() throws Exception {
    List<GlobalTransaction> globalTransactions = new ArrayList<>();
    for(int i=0;i<10;i++){
      globalTransactions.add(GlobalTransaction.builder()
          .beginTime(new Date())
          .endTime(new Date())
          .events(new ArrayList<>())
          .subTransactions(new ArrayList<>())
          .build());
    }
    when(transactionRepository.getSlowGlobalTransactionsTopN(10)).thenReturn(globalTransactions);
    mockMvc.perform(get("/alpha/api/v1/transaction/slow"))
        .andExpect(status().isOk())
        .andExpect(
            MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(jsonPath("$", hasSize(10)))
        .andReturn();
  }
}
