package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.base;

import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.platform.common.util.MesConstWords;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.bean.ListPager;
import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.common.PagerHelper;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.*;
import cn.estsh.i3plus.pojo.mes.model.report.DataTwoDimensionalModel;
import cn.estsh.i3plus.pojo.mes.model.report.MesCimSeresJisQueueSummaryResponse;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IMesContainerSnStationService;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 容器条码与站点关系表-业务方法实现
 * @Reference :
 * @Author : logic
 * @CreateDate : 2025/6/13 09:16
 * @Modify:
 **/
@Slf4j
@Service
public class MesContainerSnStationServiceImpl implements IMesContainerSnStationService {

    @Autowired
    private MesContainerSnStationRepository mesContainerSnStationRepository;
    @Autowired
    private MesContainerPackageDetailRepository packageDetailRDao;
    @Autowired
    private MesContainerPackageRepository containerPackageRDao;
    @Autowired
    private EntityManager entityManager;
    @Autowired
    private MesStationRepository mesStationRDao;

    private void packContainerSnStation(String organizeCode, MesContainerSnStation snStation, Query query) {
        query.setParameter("organizeCode", organizeCode)
                .setParameter("isValid", CommonEnumUtil.VALID)
                .setParameter("isDeleted", CommonEnumUtil.FALSE)
                .setParameter("station", snStation.getStation());
        if (!StringUtils.isEmpty(snStation.getContainerSn())){
            query.setParameter("top_container_sn", snStation.getContainerSn());
        }
    }

    @Override
    public ListPager<MesContainerSnStation> queryPager(MesContainerSnStation mesContainerSnStation, Pager pager) {
        if (StringUtils.isEmpty(mesContainerSnStation.getStation())) {
            return new ListPager<>(new ArrayList<>(), pager);
        }
        StringBuilder hql = new StringBuilder();
        hql.append(" from mes_container_sn_station mss where mss.organize_code=:organizeCode and mss.is_deleted=:isDeleted and mss.is_valid=:isValid");
        hql.append(" and mss.station=:station");
        if (!StringUtils.isEmpty(mesContainerSnStation.getContainerSn())) {
            hql.append(" and mss.top_container_sn=:top_container_sn");
        }
        hql.append(" group by mss.top_container_sn");
        StringBuilder countQueryHql= new StringBuilder();
        countQueryHql.append("select count(DISTINCT mss.top_container_sn)");
        Query countQuery = entityManager.createNativeQuery(countQueryHql.append(hql).toString());
        packContainerSnStation(mesContainerSnStation.getOrganizeCode(), mesContainerSnStation, countQuery);
        //本次查询满足条件的总数
        int count = Integer.parseInt(String.valueOf(countQuery.getSingleResult()));
        if (count <= 0) {
            return new ListPager<>(new ArrayList<>(), pager);
        }

        StringBuilder dataQueryHql = new StringBuilder();
        dataQueryHql.append("select DISTINCT mss.top_container_sn as containerSn, mss.station as station, mss.seq as seq, mss.id as id");
        Query dataQuery = entityManager.createNativeQuery(dataQueryHql.append(hql).toString());
        packContainerSnStation(mesContainerSnStation.getOrganizeCode(), mesContainerSnStation, dataQuery);

        pager = PagerHelper.getPager(pager, count);
        //查询本页数据
        dataQuery.setMaxResults(pager.getPageSize());
        dataQuery.setFirstResult(pager.getCurrentPage() * pager.getPageSize() - pager.getPageSize());
        List list = dataQuery.getResultList();
        List<MesContainerSnStation> modelList = new ArrayList<>();
        for (Object result : list) {
            Object[] cells = (Object[]) result;
            MesContainerSnStation snStation = new MesContainerSnStation();
            snStation.setContainerSn(StringUtils.isEmpty(cells[0]) ? "" : cells[0].toString());
            snStation.setStation(StringUtils.isEmpty(cells[1]) ? "" : cells[1].toString());
            snStation.setSeq(StringUtils.isEmpty(cells[2]) ? 0 : Integer.parseInt(cells[2].toString()));
            snStation.setId(StringUtils.isEmpty(cells[3]) ? 0 : Long.parseLong(cells[3].toString()));

            modelList.add(snStation);
        }
        return new ListPager<>(modelList, pager);

//        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(mesContainerSnStation.getOrganizeCode());
//        DdlPreparedPack.getStringEqualPack(mesContainerSnStation.getStation(), "station", ddlPackBean);
//        DdlPreparedPack.getStringEqualPack(mesContainerSnStation.getContainerSn(), "containerSn", ddlPackBean);
//        DdlPreparedPack.getStringEqualPack(mesContainerSnStation.getPartNo(), "partNo", ddlPackBean);
//        pager = PagerHelper.getPager(pager, mesContainerSnStationRepository.findByHqlWhereCount(ddlPackBean));
//        List<MesContainerSnStation> containerSnStationList = mesContainerSnStationRepository.findByHqlWherePage(ddlPackBean, pager);
//        return new ListPager<>(containerSnStationList, pager);
    }

    private String getTopContainerSn(String organizeCode, String containerSn) {
        MesContainerPackageDetail packageDetail = packageDetailRDao.getByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "barCode"},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), containerSn});
        if (packageDetail != null) {
            return getTopContainerSn(organizeCode, packageDetail.getContainerSn());
        }
        return containerSn;
    }

    private Boolean getBottomPackageDetails(String organizeCode, String containerSn, List<MesContainerPackageDetail> bottomPackageDetails) {
        List<MesContainerPackageDetail> packageDetailList = packageDetailRDao.findByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "containerSn"},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), containerSn});
        if (CollectionUtils.isEmpty(packageDetailList)) {
            return true;
        }
        for (MesContainerPackageDetail packageDetail : packageDetailList) {
            if (getBottomPackageDetails(organizeCode, packageDetail.getBarCode(), bottomPackageDetails)) {
                bottomPackageDetails.add(packageDetail);
            }
        }

        return false;
    }

    private void checkNotMultiplyStation(String organizeCode, String stationCode, Set<String> containerSnSet) {
        if (CollectionUtils.isEmpty(containerSnSet)) {
            return;
        }
        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(new ArrayList<>(containerSnSet), "containerSn", ddlPackBean);
        List<MesContainerSnStation> containerSnStationList = mesContainerSnStationRepository.findByHqlWhere(ddlPackBean);
        for (MesContainerSnStation snStation : containerSnStationList) {
            if (!snStation.getStation().equals(stationCode)) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("此容器已绑定站点【%s】!", snStation.getStation())
                        .build();
            }
        }
    }

    @Override
    public void doInsert(MesContainerSnStation mesContainerSnStation, String userName) {
        final String organizeCode = mesContainerSnStation.getOrganizeCode();
        if (!mesStationRDao.isExitByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "station"},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), mesContainerSnStation.getStation()})) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("站点【%s】不存在，请检测主数据!", mesContainerSnStation.getStation())
                    .build();
        }
        String topContainerSn = getTopContainerSn(organizeCode, mesContainerSnStation.getContainerSn());
        if (!topContainerSn.equals(mesContainerSnStation.getContainerSn())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("此容器已绑定容器条码【%s】，请扫描容器条码【%s】!", mesContainerSnStation.getContainerSn(), topContainerSn)
                    .build();
        }
        //校验容器条码的唯一性
        DdlPackBean containerSnStationDdlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(mesContainerSnStation.getContainerSn(), "topContainerSn", containerSnStationDdlPackBean);
        if (mesContainerSnStationRepository.isExitByHql(containerSnStationDdlPackBean)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("容器条码【%s】已存在!", mesContainerSnStation.getContainerSn())
                    .build();
        }
        checkStationTypeBindContainerSn(organizeCode, mesContainerSnStation.getStation(), mesContainerSnStation.getContainerSn());
        List<MesContainerPackageDetail> bottomPackageDetailList = new ArrayList<>();
        getBottomPackageDetails(organizeCode, mesContainerSnStation.getContainerSn(), bottomPackageDetailList);
        final Set<String> containerSnSet = bottomPackageDetailList.stream().map(MesContainerPackageDetail::getContainerSn).collect(Collectors.toSet());
        checkNotMultiplyStation(organizeCode, mesContainerSnStation.getStation(), containerSnSet);

        //根据站点 + 设备代码的组合查询现有数据中最大的顺序号，新增数据的顺序号在最大值的基础上加一
        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(mesContainerSnStation.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(mesContainerSnStation.getStation(), "station", ddlPackBean);
        DdlPreparedPack.getOrderByPack(
                new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()},
                new String[]{"seq"}, ddlPackBean);
        List<MesContainerSnStation> oldContainerSnStationList =
                mesContainerSnStationRepository.findByHqlTopWhere(ddlPackBean, 1);
        int seq;
        if (CollectionUtils.isEmpty(oldContainerSnStationList)) {
            seq = 1;
        }else {
            if (Objects.isNull(oldContainerSnStationList.get(0)) ||
                    Objects.isNull(oldContainerSnStationList.get(0).getSeq())) {
                seq = 1;
            }else {
                seq = oldContainerSnStationList.get(0).getSeq() + 1;
            }
        }
        if (CollectionUtils.isEmpty(bottomPackageDetailList)) {
            MesContainerSnStation snStation = new MesContainerSnStation();
            snStation.setOrganizeCode(organizeCode);
            snStation.setStation(mesContainerSnStation.getStation());
            snStation.setContainerSn(mesContainerSnStation.getContainerSn());
            snStation.setTopContainerSn(topContainerSn);
            snStation.setSeq(seq);
            ConvertBean.serviceModelInitialize(snStation, userName);
            mesContainerSnStationRepository.insert(snStation);
        } else {
            for (String containerSn : containerSnSet) {
                MesContainerSnStation snStation = new MesContainerSnStation();
                snStation.setOrganizeCode(organizeCode);
                snStation.setStation(mesContainerSnStation.getStation());
                snStation.setContainerSn(containerSn);
                snStation.setTopContainerSn(topContainerSn);
                snStation.setSeq(seq);
                ConvertBean.serviceModelInitialize(snStation, userName);
                mesContainerSnStationRepository.insert(snStation);
            }
        }
    }

    /**
     * 校验站点类型与容器得开关箱状态
     * @param organizeCode 工厂代码
     * @param station 站点
     * @param containerSn 容器条码
     */
    private void checkStationTypeBindContainerSn(String organizeCode, String station, String containerSn) {
        MesStation mesStation = mesStationRDao.getByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "station"},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), station});
        if (mesStation == null) {
            return;
        }
        if (mesStation.getStationType() == null) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("站点【%s】类型不能为空，请检查数据!", station)
                    .build();
        }
        if (mesStation.getStationType() == MesExtEnumUtil.STATION_TYPE.STATION_TYPE_10.getValue() ||
                mesStation.getStationType() == MesExtEnumUtil.STATION_TYPE.STATION_TYPE_20.getValue()) {
            // 只能绑定已关箱容器
            MesContainerPackage containerPackage = containerPackageRDao.getByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "containerSn"},
                    new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), containerSn});
            if (containerPackage == null || !Objects.equals(containerPackage.getPackageStatus(), MesExtEnumUtil.CONTAINER_PACKAGE_STATUS.STATUS_20.getValue())) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("站点[%s]只能绑定已关箱的容器[%s]，请检查数据!", station, containerSn)
                        .build();
            }
        } else if (mesStation.getStationType() == MesExtEnumUtil.STATION_TYPE.STATION_TYPE_30.getValue() ||
                mesStation.getStationType() == MesExtEnumUtil.STATION_TYPE.STATION_TYPE_50.getValue()) {
            // 只能绑定未关箱容器
            MesContainerPackage containerPackage = containerPackageRDao.getByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "containerSn"},
                    new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), containerSn});
            if (containerPackage != null && Objects.equals(containerPackage.getPackageStatus(), MesExtEnumUtil.CONTAINER_PACKAGE_STATUS.STATUS_20.getValue())) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("站点[%s]只能绑定未关箱的容器[%s]，请检查数据!", station, containerSn)
                        .build();
            }
        }
    }

    @Override
    public void deleteWeaklyByIds(List<Long> idList, String organizeCode, String userName) {
        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getInPackList(idList, "id", ddlPackBean);
        mesContainerSnStationRepository.updateByProperties(
                new String[]{"modifyUser", "modifyDatetime", "isDeleted"},
                new Object[]{userName, TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()},
                ddlPackBean);
    }

    @Override
    public void checkStation(String organizeCode, String station) {
        if (!mesStationRDao.isExitByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "station"},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), station})) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("站点【%s】不存在，请检查数据!", station)
                    .build();
        }
    }

}
