package com.prolog.eis.service.container.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.prolog.eis.constants.base.LocationWorkAreaConstants;
import com.prolog.eis.core.model.biz.route.ContainerLocation;
import com.prolog.eis.dao.container.ContainerInfoDetailMapper;
import com.prolog.eis.dao.container.LocationCfgMapper;
import com.prolog.eis.model.container.ContainerInfoDetail;
import com.prolog.eis.model.container.LocationCfg;
import com.prolog.eis.service.container.LocationCfgService;
import com.prolog.eis.service.feign.RouteFeignService;
import com.prolog.eis.utils.ResultUtils;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.utils.AssertUtils;
import com.prolog.framework.utils.MapUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zmr
 * @description: 关键点位配置表-服务实现类
 * @date 2023-07-06 11:29
 */
@Service
@RequiredArgsConstructor
public class LocationCfgServiceImpl implements LocationCfgService {

    @Value("${mcs.mcs-change-station}")
    private String url;

    private final LocationCfgMapper locationCfgMapper;
    private final RouteFeignService plgFeignRouteService;
    private final ContainerInfoDetailMapper containerInfoDetailMapper;
    private final RestTemplate newRestTemplate;

    /**
     * 新增数据
     *
     * @param locationCfg 关键点位配置表
     */
    @Override
    public long save(LocationCfg locationCfg) {
        return locationCfgMapper.save(locationCfg);
    }

    /**
     * 新增批量数据
     *
     * @param locationCfgList 关键点位配置表
     */
    @Override
    public long saveBatch(List<LocationCfg> locationCfgList) {
        return locationCfgMapper.saveBatch(locationCfgList);
    }

    /**
     * 查询多条数据
     *
     * @param paramMap 查询起始位置
     * @return 对象列表
     */
    @Override
    public List<LocationCfg> findByMap(Map<String, Object> paramMap) {
        return locationCfgMapper.findByMap(paramMap, LocationCfg.class);
    }

    /**
     * 查询单条数据
     *
     * @param paramMap 查询起始位置
     * @return 对象
     */
    @Override
    public LocationCfg findOneByMap(Map<String, Object> paramMap) {
        List<LocationCfg> dataList = findByMap(paramMap);
        if(dataList.isEmpty()) {
            return null;
        }
        return dataList.get(0);
    }

    /**
     * 查询多条数据
     *
     * @param criteria 查询起始位置
     * @return 对象列表
     */
    @Override
    public List<LocationCfg> findByCriteria(Criteria criteria) {
        return locationCfgMapper.findByCriteria(criteria);
    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public LocationCfg findById(int id) {
        return locationCfgMapper.findById(id, LocationCfg.class);
    }

    /**
     * 修改数据
     *
     * @param locationCfg 实例对象
     */
    @Override
    public long update(LocationCfg locationCfg) {
        return locationCfgMapper.update(locationCfg);
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     */
    @Override
    public long deleteById(int id) {
        return locationCfgMapper.deleteById(id, LocationCfg.class);
    }

    /**
     * 通过参数删除数据
     *
     * @param paramMap 参数
     */
    @Override
    public long deleteByMap(Map<String, Object> paramMap) {
        return locationCfgMapper.deleteByMap(paramMap, LocationCfg.class);
    }

    /**
     * 通过参数查询总条数
     *
     * @param paramMap 参数
     */
    @Override
    public long findCountByMap(Map<String, Object> paramMap) {
        return locationCfgMapper.findCountByMap(paramMap, LocationCfg.class);
    }


    @Override
    public ContainerLocation findLocationByContainer(ContainerLocation containerLocation) throws Exception {
        String containerNo = "";
        String palletNo = "";
        if (StrUtil.isNotBlank(containerLocation.getPalletNo())){
            palletNo = containerLocation.getPalletNo();
        }else if (StrUtil.isNotBlank(containerLocation.getContainerNo())){
            ContainerInfoDetail containerInfoDetail = containerInfoDetailMapper.findByMap(MapUtils.put("containerSubNo", containerLocation.getContainerNo()).getMap(), ContainerInfoDetail.class)
                    .stream().findFirst().orElseThrow(() -> new PrologException("未查询到托盘信息"));
            containerNo = containerInfoDetail.getContainerNo();
        }
        if (StrUtil.isBlank(palletNo)){
            throw new PrologException("载具和容器都为空，请重新输入载具和容器");
        }

        ContainerLocation location  = plgFeignRouteService.seachLocationNo(MapUtils.put("containerNo",containerNo).getMap());

        if (StrUtil.isNotBlank(containerNo)){
            location.setContainerNo(containerNo);
        }
        return location;
    }

    @Override
    public List<String> findAvailableArea() {
        List<LocationCfg> locationCfgList = locationCfgMapper.findByMap(MapUtils.put("type", LocationWorkAreaConstants.OUTBOUND_WORK_TYPE).getMap(), LocationCfg.class);
        List<String> list = locationCfgList.stream().map(LocationCfg::getAreaNo).distinct().collect(Collectors.toList());
        return list;
    }

    @Override
    public List<LocationCfg> findLocationByarea(String area) {
        List<LocationCfg> areaNo = locationCfgMapper.findByMap(MapUtils.put("areaNo", area).getMap(), LocationCfg.class);
        return areaNo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDirectionUrl(String type) {
        List<LocationCfg> locationCfgList = locationCfgMapper.findByMap(null,LocationCfg.class);
        LocationCfg locationCfg = locationCfgList.stream().filter(o -> o.getRouteDirectionType().contains(type)).findFirst().orElse(null);

        //出库改为入库 终点位置
        //入库改为出库 起点位置
        Integer directionType = 20;
        String[] directionArr = locationCfg.getRouteDirectionType().split(",");
        for (String direction : directionArr) {
            if(Integer.parseInt(type) < Integer.parseInt(direction)){
                //如果当前要切换的存在小于配置的为入库  切换为入库需比出库小
                directionType = 10;
            }
        }
        locationCfg.setDirection(directionType);
        this.update(locationCfg);
        //location_no取locationCfg的，方向取stationCfg的
        //mcs接口方向切换下发
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("coord", locationCfg.getLocationNo());
        jsonObject.put("direction", directionType);
        ResultUtils resultUtils = newRestTemplate.postForObject(url, jsonObject, ResultUtils.class);
        AssertUtils.isNotTrue(resultUtils.getRet().equals("false"), resultUtils.getMsg());
    }

    @Override
    public synchronized LocationCfg getLocationCfgOccupy(String containerNo) {
        Criteria criteria=new Criteria(LocationCfg.class);
        criteria.restrictionBuilder().eq(LocationCfg::getType, 10).eq(LocationCfg::getDirection, 10).isnull(LocationCfg::getContainerNo).build();
        LocationCfg locationCfg = this.findByCriteria(criteria).stream().findFirst().orElse(null);
        if (Objects.nonNull(locationCfg)) {
            locationCfg.setContainerNo(containerNo);
            locationCfg.setUpdateTime(LocalDateTime.now());
            this.update(locationCfg);
        }
        return locationCfg;
    }
}
