package com.tykj.dev.confirmcheck;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.tykj.dev.device.confirmcheck.controller.DeviceCheckController;
import com.tykj.dev.device.confirmcheck.entity.vo.CheckBillVo;
import com.tykj.dev.device.confirmcheck.entity.vo.CheckDetailVo;
import com.tykj.dev.device.confirmcheck.entity.vo.CheckStatVo;
import com.tykj.dev.device.confirmcheck.entity.vo.DevLibVo;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckDetailDao;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckStatDao;
import com.tykj.dev.device.confirmcheck.utils.ObjTransUtil;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.task.repository.TaskDao;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.user.base.enums.AuExample;
import com.tykj.dev.device.user.subject.dao.AreaDao;
import com.tykj.dev.device.user.subject.dao.UnitsDao;
import com.tykj.dev.device.user.subject.service.AuService;
import com.tykj.dev.union.BaseTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.StreamSupport;

import static com.tykj.dev.misc.utils.JacksonUtil.toJSon;
import static java.util.stream.Collectors.toList;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * DeviceCheckControllerTest.
 *
 * @author Matrix <xhyrzldf@gmail.com>
 * @since 2020/9/15 at 11:17 上午
 */
@SuppressWarnings("ALL")
@WithMockUser(username = "shena", password = "qwer1234", authorities = "省A专管员")
@ActiveProfiles("test")
class DeviceCheckControllerTest extends BaseTest {

    private static Task initTask;
    @Autowired
    protected MockMvc mockMvc;
    ObjectMapper objectMapper = new ObjectMapper();
    RequestBuilder request;
    Integer detailBillId;
    String baseUrl = "/check/confirm/detail/";
    @Autowired
    private DeviceCheckController checkController;
    @Autowired
    private DeviceCheckDetailDao detailRepo;
    @Autowired
    private DeviceCheckStatDao statRepo;
    @Autowired
    private DeviceLibraryDao deviceRepo;
    @Autowired
    private AreaDao areaRepo;
    @Autowired
    private UnitsDao unitsDao;
    @Autowired
    private TaskDao taskRepo;
    @Autowired
    private ObjTransUtil transUtil;
    @Autowired
    private AuService auService;


    @Test
    void startAutoCheck() throws Exception {
        // 测试
        RequestBuilder request;

        request = post("/check/confirm/auto")
                .header("Origin", "*");


        MvcResult mvcResult = mockMvc.perform(request)
                .andExpect(status().isOk())
                .andReturn();
        String resultString = mvcResult.getResponse().getContentAsString();
        System.out.println("[测试结果] 自动发起核查任务测试通过,返回结果为 : " +
                resultString);
        // 测试 生成的数据是否都能正常访问
        JsonNode jsonNode = objectMapper.readTree(resultString);
        StreamSupport
                .stream(jsonNode.get("data").get("statId").spliterator(), false)
                .map(JsonNode::asInt)
                .forEach(statId -> {
                    //测试访问
                    CheckStatVo statRes = checkController.findStatById(statId);
                    try {
                        System.out.println(objectMapper.writeValueAsString(statRes));
                    } catch (JsonProcessingException e) {
                        System.out.println("数据转JSON发生异常");
                        e.printStackTrace();
                    }
                    System.out.printf("[数据清理-统计] 删除id为 %d 的统计数据 %n", statId);
//                    statRepo.deleteById(statId);
                });
        StreamSupport
                .stream(jsonNode.get("data").get("detailId").spliterator(), false)
                .map(JsonNode::asInt)
                .forEach(detailId -> {
                    //测试访问
                    checkController.findDetail(detailId);
                    System.out.printf("[数据清理-自查] 删除id为 %d 的自查数据 %n", detailId);
//                    detailRepo.deleteById(detailId);
                });
        StreamSupport
                .stream(jsonNode.get("data").get("taskId").spliterator(), false)
                .map(JsonNode::asInt)
                .forEach(taskId -> {
                    System.out.printf("[数据清理-任务] 删除id为 %d 的任务数据 %n", taskId);
//                    taskRepo.deleteById(taskId);
                });
    }

    @Test
    void checkUserA() throws Exception {
        // checkUserA 接口
//        initTask = taskRepo.findAll(Specifications.<Task>and()
//                .eq("billStatus", StatusEnum.CHECK_DETAIL_0.id)
//                .build())
//                .get(0);

        initTask = taskRepo.findById(741).get();

        detailBillId = initTask.getBillId();

        CheckDetailVo detailVoList = detailRepo.findById(detailBillId)
                .map(transUtil::CheckDetailDo2Vo)
                .orElse(null);

        DevLibVo devLibVo = new DevLibVo(detailVoList.getDevInLibrary(), detailVoList.getDevNotInLibrary());

        devLibVo.getDevInLibrary().forEach(d -> d.setProofResult(1));

        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("assignUserId", "2");
        paramMap.put("checkResult", "\"检查结果无误\"");

        String url_a = baseUrl + "A/" + detailBillId;
        StringJoiner joiner = new StringJoiner("&", "?", "");

        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String k = entry.getKey();
            String v = entry.getValue();
            joiner.add(k + "=" + v);
        }
        url_a += joiner.toString();
        System.out.println("url is " + url_a);
        request = put(url_a)
                .header("Origin", "*")
                .contentType(MediaType.APPLICATION_JSON)
                .content(toJSon(devLibVo));

        mockMvc.perform(request)
                .andExpect(status().isOk())
                .andDo(s -> System.out.println(
                        String.format("[测试结果] 对任务id=%d的任务执行岗位A详情审核操作成功，审核的详情表id为%d",
                                initTask.getId(),
                                initTask.getBillId())));

    }

    @Test
    void checkUserA2D() throws Exception {

        initTask = taskRepo.findById(748).get();

        detailBillId = initTask.getBillId();

        CheckDetailVo detailVoList = detailRepo.findById(detailBillId)
                .map(transUtil::CheckDetailDo2Vo)
                .orElse(null);

        DevLibVo devLibVo = new DevLibVo(detailVoList.getDevInLibrary(), detailVoList.getDevNotInLibrary());

        devLibVo.getDevInLibrary().forEach(d -> d.setProofResult(1));

        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("assignUserId", "2");
        paramMap.put("checkResult", "\"检查结果无误\"");

        String url_a = baseUrl + "A/" + detailBillId;
        StringJoiner joiner = new StringJoiner("&", "?", "");

        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String k = entry.getKey();
            String v = entry.getValue();
            joiner.add(k + "=" + v);
        }
        url_a += joiner.toString();
        System.out.println("url is " + url_a);
        request = put(url_a)
                .header("Origin", "*")
                .contentType(MediaType.APPLICATION_JSON)
                .content(toJSon(devLibVo));

        mockMvc.perform(request)
                .andExpect(status().isOk())
                .andDo(s -> System.out.println(
                        String.format("[测试结果] 对任务id=%d的任务执行岗位A详情审核操作成功，审核的详情表id为%d",
                                initTask.getId(),
                                initTask.getBillId())));


        // checkUserB 接口 测试审核通过
        String url_b = baseUrl + "B/" + detailBillId + "?" + "checkStatus=1&checkUserAId=3&checkUserBId=4";
        request = put(url_b)
                .header("Origin", "*");

        mockMvc.perform(request)
                .andExpect(status().isOk())
                .andDo(s -> System.out.println(
                        String.format("[测试结果] 对任务id=%d的任务执行岗位B详情审核操作成功，审核的详情表id为%d",
                                initTask.getId(),
                                initTask.getBillId())));

        // checkUserC - C 接口 测试审核通过
        String url_c = baseUrl + "C/" + detailBillId + "?" + "pass=true";
        request = put(url_c)
                .header("Origin", "*");

        mockMvc.perform(request)
                .andExpect(status().isOk())
                .andDo(s -> System.out.println(
                        String.format("[测试结果] 对任务id=%d的任务执行岗位C详情审核操作成功，审核的详情表id为%d",
                                initTask.getId(),
                                initTask.getBillId())));

        // checkUserC - D 接口 测试审核通过
        String url_d = baseUrl + "C/" + detailBillId + "?" + "pass=true";
        request = put(url_d)
                .header("Origin", "*");

        mockMvc.perform(request)
                .andExpect(status().isOk())
                .andDo(s -> System.out.println(
                        String.format("[测试结果] 对任务id=%d的任务执行岗位D详情审核操作成功，审核的详情表id为%d",
                                initTask.getId(),
                                initTask.getBillId())));
    }

    @Test
    void verifyStat() throws Exception {
        // 统计数据确认接口
        // 获取父级的billId
        Integer statTaskId = initTask.getParentTaskId();
        Integer statId = taskRepo.findById(statTaskId).get().getBillId();
        String url_verify = "/check/confirm/stat/verify?statId=" + statId;
        request = post(url_verify)
                .header("Origin", "*");

        mockMvc.perform(request)
                .andExpect(status().isOk())
                .andDo(s -> System.out.println(
                        String.format("[测试结果] 对任务id=%d的任务执行统计数据确认操作成功，审核的数据表id为%d",
                                statTaskId,
                                statId)));
    }

    @Test
    void startManualCheck() throws Exception {


        CheckBillVo param = new CheckBillVo();
        param.setUnitId(1);
        List<Integer> checkedUnitIds = Lists.newArrayList(1);
        param.setAreaRange(checkedUnitIds);
        param.setCheckTitle("单元测试手动核查");
        param.setRemark("这是一段测试用的数据");
        param.setUserAId(1);
        param.setUserBId(2);


        // 测试发起核查

        request = post("/check/confirm/manual")
                .header("Origin", "*")
                .contentType(MediaType.APPLICATION_JSON)
                .content(toJSon(param));

        String content = mockMvc.perform(request)
                .andExpect(status().isOk())
                .andReturn().getResponse().getContentAsString();

        // 检查手动发起核查数据的有效性
        // 统计数据是合理的，通过查询查询指定单位的装备的数量来核对deviceCount,supposeCount与suppose
        List<Integer> statIds = StreamSupport
                .stream(objectMapper.readTree(content).get("data").get("statIds").spliterator(), false)
                .map(JsonNode::asInt)
                .collect(toList());

        // 测试auService
        checkedUnitIds.stream()
                .map(uid -> auService.findOne(AuExample.UnitId, uid))
                .forEach(System.out::println);

    }
}