package com.fjhx.material.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.Condition;
import com.fjhx.entity.material.MaterialReceiving;
import com.fjhx.entity.material.MaterialReceivingDetails;
import com.fjhx.material.mapper.MaterialReceivingMapper;
import com.fjhx.material.service.MaterialReceivingDetailsService;
import com.fjhx.material.service.MaterialReceivingService;
import com.fjhx.params.material.MaterialReceivingVo;
import com.fjhx.utils.Assert;
import com.fjhx.utils.WrapperUtil;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 物料接收 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-10-11
 */
@Slf4j
@Service
public class MaterialReceivingServiceImpl extends ServiceImpl<MaterialReceivingMapper, MaterialReceiving> implements MaterialReceivingService {

    @Autowired
    private MaterialReceivingDetailsService materialReceivingDetailsService;

    private final RestTemplate restTemplate = new RestTemplate();

    @Override
    public Page<MaterialReceiving> getPage(Map<String, String> condition) {

        QueryWrapper<MaterialReceiving> wrapper = Wrappers.query();

        WrapperUtil.init(condition, wrapper)
                .createTimeDesc();

        Page<MaterialReceiving> page = page(condition, wrapper);
        return page;
    }

    @Override
    public void add(MaterialReceivingVo materialReceivingVo) {
        save(materialReceivingVo);
    }

    @Override
    public void edit(MaterialReceivingVo materialReceivingVo) {
        updateById(materialReceivingVo);
    }

    @Override
    public void delete(MaterialReceivingVo materialReceivingVo) {
        removeById(materialReceivingVo.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void submit(MaterialReceivingVo materialReceivingVo) {

        materialReceivingVo.setSubmitTime(new Date());

        Integer type = materialReceivingVo.getType();
        Assert.notEmpty(type, "提交类型不能为空");

        if (type.equals(2)) {
            String flowLinkId = IdWorker.getIdStr();

            materialReceivingVo.setFlowLinkId(flowLinkId);
            materialReceivingVo.setApproveBillState(0);

            // 发起审批流
            baseMapper.insertFlowApplyCheck(
                    IdWorker.getIdStr(),
                    "202208240000000000000000001",
                    "20220824000000000000000000101",
                    null,
                    "20220824000000000000000000102",
                    materialReceivingVo.getSubmitUserId(),
                    0,
                    null,
                    flowLinkId,
                    "物料接收"
            );
        }

        save(materialReceivingVo);

        // 物料接收id
        Long materialReceivingId = materialReceivingVo.getId();

        List<String> rfidItems = materialReceivingVo.getRfidItems();

        List<MaterialReceivingDetails> materialReceivingDetailsList = rfidItems.stream().map(rfid -> {
            MaterialReceivingDetails materialReceivingDetails = new MaterialReceivingDetails();
            materialReceivingDetails.setMaterialReceivingId(materialReceivingId);
            materialReceivingDetails.setRfid(rfid);
            materialReceivingDetails.setStatus(type.equals(2) ? 1 : 2);

            return materialReceivingDetails;
        }).collect(Collectors.toList());

        materialReceivingDetailsService.saveBatch(materialReceivingDetailsList);
    }

    @Override
    public List<Map<String, Object>> getList(MaterialReceivingVo materialReceivingVo) {

        List<Map<String, Object>> list = baseMapper.getList(materialReceivingVo.getReceiveUserAccount());

        if (list.size() > 0) {
            setUserName(list);
        }

        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void operation(Condition condition) {
        List<Long> idList = condition.getArray("idList", Long.class);
        Integer operation = condition.getInt("operation", "操作类型不能为空");

        Assert.notEmpty(idList, "物料接受id列表不能为空");

        if (operation != 3 && operation != 4) {
            throw new ServiceException("操作类型不正确");
        }

        List<MaterialReceivingDetails> list = materialReceivingDetailsService.listByIds(idList);

        Set<Long> materialReceivingIdSet = new HashSet<>();
        Date date = new Date();

        for (MaterialReceivingDetails materialReceivingDetails : list) {
            materialReceivingDetails.setStatus(operation);
            materialReceivingDetails.setHandleTime(date);
            materialReceivingIdSet.add(materialReceivingDetails.getMaterialReceivingId());
        }

        materialReceivingDetailsService.updateBatchById(list);

        // 如果确认接收,出库
        if (operation == 3) {

            // 查询领料记录
            List<MaterialReceiving> materialReceivingList = listByIds(materialReceivingIdSet);

            // 根据领料记录把rfid分组
            Map<Long, List<String>> rfidMap = list.stream().collect(Collectors.toMap(
                    MaterialReceivingDetails::getMaterialReceivingId,
                    item -> Collections.singletonList(item.getRfid()),
                    (v1, v2) -> {
                        v1.addAll(v2);
                        return v1;
                    }
            ));

            // 调用原出库接口
            materialReceivingList.forEach(item -> issueRest(item, rfidMap.get(item.getId())));
        }

    }

    @Override
    public List<Map<String, Object>> flowDetails(Condition condition) {
        String flowLinkId = condition.getStr("flowLinkId");
        List<Map<String, Object>> list = baseMapper.flowDetails(flowLinkId);

        if (list.size() > 0) {
            setUserName(list);
        }

        return list;
    }

    @Override
    public void handleFlow(Condition condition) {
        // 操作人id
        String checkUserId = condition.getStr("checkUserId");
        // 流程关联id
        String flowLinkId = condition.getStr("flowLinkId", "流程关联id不能为空");
        // 2=审批通过，3=审批驳回
        Integer checkState = condition.getInt("checkState", "审批结果不能为空");
        // 审批意见
        String suggestions = condition.getStr("suggestions");

        String materialReceivingId = condition.getStr("materialReceivingId", "物料出库id不能为空");

        // 修改审批流
        baseMapper.insertFlowApplyCheck(
                IdWorker.getIdStr(),
                "202208240000000000000000001",
                "20220824000000000000000000102",
                "20220824000000000000000000101",
                null,
                checkUserId,
                checkState,
                suggestions,
                flowLinkId,
                "物料接收"
        );

        if (checkState == 2) {
            materialReceivingDetailsService.update(
                    Wrappers.<MaterialReceivingDetails>lambdaUpdate()
                            .eq(MaterialReceivingDetails::getMaterialReceivingId, materialReceivingId)
                            .set(MaterialReceivingDetails::getStatus, 2)
            );
        }

    }

    @Override
    public List<Map<String, Object>> toBeReceivedList(Condition condition) {
        String submitUserAccount = condition.getStr("submitUserAccount", "提交人账号不能为空");

        List<Map<String, Object>> list = baseMapper.toBeReceivedList(submitUserAccount);

        if (list.size() > 0) {
            setUserName(list);
        }

        return list;
    }

    @Override
    public void ignore(MaterialReceivingDetails materialReceivingDetails) {
        materialReceivingDetails.setStatus(5);
        materialReceivingDetailsService.updateById(materialReceivingDetails);
    }


    /**
     * 通过用户账号获取用户名称
     *
     * @param accountList 账号列表
     * @return 账号、名称 Map
     */
    private Map<String, String> getUserNameByAccount(List<String> accountList) {
        accountList = accountList.stream().distinct().collect(Collectors.toList());
        return baseMapper.getUserNameByAccount(Wrappers.query().in("aa.AccountNo", accountList))
                .stream().collect(Collectors.toMap(
                        item -> item.get("account"),
                        item -> item.get("userName")
                ));
    }

    /**
     * 赋值提交人名称和接收人名称
     */
    private void setUserName(List<Map<String, Object>> list) {
        List<String> accountList = new ArrayList<>();

        for (Map<String, Object> map : list) {
            accountList.add(map.get("submitUserAccount").toString());
            accountList.add(map.get("receiveUserAccount").toString());
        }

        Map<String, String> userNameByAccount = getUserNameByAccount(accountList);

        for (Map<String, Object> map : list) {
            map.put("submitUserName", userNameByAccount.get(map.get("submitUserAccount").toString()));
            map.put("receiveUserName", userNameByAccount.get(map.get("receiveUserAccount").toString()));
        }
    }

    /**
     * 调用原出库接口
     */
    private void issueRest(MaterialReceiving materialReceiving, List<String> rfidList) {

        JSONObject httpBody = new JSONObject();
        httpBody.put("userId", materialReceiving.getUserId());
        httpBody.put("plcCode", materialReceiving.getPlcCode());
        httpBody.put("rfidItems", rfidList);
        httpBody.put("stockChangeType", materialReceiving.getStockChangeType());
        httpBody.put("remark", materialReceiving.getRemark());
        httpBody.put("token", materialReceiving.getToken());

        // 设置请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("TargetCode", "3");
        httpHeaders.set("Content-Type", "application/json");

        HttpEntity<String> httpEntity = new HttpEntity<>(httpBody.toJSONString(), httpHeaders);

        String result = restTemplate.postForObject("http://120.79.80.64:8002/api/StockInOut/HandleMacStockInOut", httpEntity, String.class);

        log.error("issueRest:" + result);
    }

//    public static void main(String[] args) {
//        RestTemplate restTemplate = new RestTemplate();
//
//        JSONObject httpBody = new JSONObject();
//        httpBody.put("userId", "1807047");
//        httpBody.put("plcCode", "1");
//        httpBody.put("rfidItems", Collections.singletonList("F00000000000000000001298"));
//        httpBody.put("stockChangeType", "20");
//        httpBody.put("remark", "");
//        httpBody.put("token", "27b0717ff1f84379a3abc961f8651032");
//
//        // 设置请求头
//        HttpHeaders httpHeaders = new HttpHeaders();
//        httpHeaders.set("TargetCode", "3");
//        httpHeaders.set("Content-Type", "application/json");
//
//        HttpEntity<String> httpEntity = new HttpEntity<>(httpBody.toJSONString(), httpHeaders);
//
//        String result = restTemplate.postForObject("http://120.79.80.64:8002/api/StockInOut/HandleMacStockInOut", httpEntity, String.class);
//
//        System.out.println(result);
//
//    }


}
