package com.ktg.iscs.service.impl;

import cn.hutool.core.lang.Assert;
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.ktg.common.annotation.MarsDataScope;
import com.ktg.common.core.text.Convert;
import com.ktg.common.exception.ServiceException;
import com.ktg.common.utils.DictUtils;
import com.ktg.common.utils.bean.BeanUtils;
import com.ktg.iscs.domain.*;
import com.ktg.iscs.domain.dto.sop.AddMarsSopDTO;
import com.ktg.iscs.domain.dto.sop.PageSopDTO;
import com.ktg.iscs.domain.vo.sop.ImportSopVO;
import com.ktg.iscs.domain.vo.sop.MarsSopDetailVO;
import com.ktg.iscs.domain.vo.sop.SopPageVO;
import com.ktg.iscs.mapper.IsSopMapper;
import com.ktg.iscs.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SOP信息Service业务层处理
 *
 * @author cgj
 * @date 2024-10-18
 */
@Service
public class IsMarsSopServiceImpl extends ServiceImpl<IsSopMapper, IsSop> implements IIsMarsSopService {
    @Autowired
    private IsSopMapper isSopMapper;
    @Autowired
    private IIsSopPointsService iIsSopPointsService;
    @Autowired
    private IIsMachineryPointsService iIsMachineryPointsService;
    @Autowired
    private IIsWorkstationService iIsWorkstationService;
    @Autowired
    private IIsMachineryService isMachineryService;

    /**
     * 查询SOP信息
     *
     * @param sopId SOP信息主键
     * @return SOP信息
     */
    @Override
    public MarsSopDetailVO selectIsMarsSopBySopId(Long sopId) {
        // 1.查询基础数据
        MarsSopDetailVO marsSopDetailVO = isSopMapper.selectIsMarsSopBySopId(sopId);
        // 2.查询sop隔离点关联数据
        List<IsSopPoints> isSopPoints = iIsSopPointsService.list(Wrappers.<IsSopPoints>lambdaQuery()
                .eq(IsSopPoints::getSopId, sopId));
        if (!isSopPoints.isEmpty()) {
            List<Long> pointIdList = isSopPoints.stream().map(IsSopPoints::getPointId).collect(Collectors.toList());
            marsSopDetailVO.setPointIdList(pointIdList);
        }
        return marsSopDetailVO;
    }

    /**
     * 查询SOP信息列表
     *
     * @param isSop SOP信息
     * @return SOP信息
     */
    @Override
    public List<IsSop> selectIsMarsSopList(IsSop isSop) {
        return isSopMapper.selectIsSopList(isSop);
    }

    /**
     * 新增SOP信息
     *
     * @param dto SOP信息
     * @return 结果
     */
    @Transactional
    @Override
    public Boolean insertIsMarsSop(AddMarsSopDTO dto) {
        // 断言校验
        // 1.判断工艺必选
        Assert.notNull(dto.getWorkstationId(), "岗位id不可为空!");
        // Assert.notNull(dto.getMachineryId(), "设备工艺id不可为空!");
        // List<IsSop> list = list(Wrappers.<IsSop>lambdaQuery().eq(IsSop::getSopCode, dto.getSopCode()));
        // Assert.isTrue(list.isEmpty(), "该SOP编号已被使用!");
        // 1.1开始生成默认名称
        String sopName = generateName(dto.getWorkstationId(), dto.getMachineryId(), dto.getSopType(), dto.getSopId());
        dto.setSopName(sopName);
        // 2.开始新增sop数据
        IsSop isSop = BeanUtils.toBean(dto, IsSop.class);
        save(isSop);
        // 3.新增隔离点和sop的关联关系
        saveSopPoints(isSop.getSopId(), dto.getMachineryId());
        return true;
    }

    /**
     * 修改SOP信息
     *
     * @param dto SOP信息
     * @return 结果
     */
    @Transactional
    @Override
    public Boolean updateIsMarsSop(AddMarsSopDTO dto) {
        // 断言校验
        Assert.notNull(dto.getSopId(), "sopId不可为空!");
        Assert.isTrue(StringUtils.isNotBlank(dto.getSopName()), "SOP名称不可为空!");
        // Assert.isTrue(StringUtils.isNotBlank(dto.getSopCode()), "SOP编号名称不可为空!");
        /*List<IsSop> list = list(Wrappers.<IsSop>lambdaQuery()
                .eq(IsSop::getSopCode, dto.getSopCode())
                .ne(IsSop::getSopId, dto.getSopId()));
        Assert.isTrue(list.isEmpty(), "该SOP编号已被使用!");*/
        // 1.判断工艺必选
        Assert.notNull(dto.getMachineryId(), "设备工艺id不可为空!");
        // 1.1开始生成默认名称
        String sopName = generateName(dto.getWorkstationId(), dto.getMachineryId(), dto.getSopType(), dto.getSopId());
        dto.setSopName(sopName);
        // 3.新增隔离点和sop的关联关系
        iIsSopPointsService.remove(Wrappers.<IsSopPoints>lambdaQuery()
                .eq(IsSopPoints::getSopId, dto.getSopId()));
        saveSopPoints(dto.getSopId(), dto.getMachineryId());
        // 4.开始执行更新操作
        IsSop isSop = BeanUtils.toBean(dto, IsSop.class);
        isSopMapper.updateById(isSop);
        return true;
    }

    /**
     * 自动生成sop名称
     * @param workstationId
     * @param machineryId
     * @param sopType
     * @return
     */
    public String generateName(Long workstationId, Long machineryId, String sopType, Long sopId) {
        IsWorkstation workstation = iIsWorkstationService.getById(workstationId);
        Assert.notNull(workstation, "岗位信息不存在！");
        IsMachinery machinery = isMachineryService.getById(machineryId);
        Assert.notNull(machinery, "设备工艺信息不存在！");
        // 如果岗位是多级
        Assert.notNull(workstation, "岗位信息不存在！");
        String workstationName = workstation.getWorkstationName();
        // 2.1如果岗位是有父级的，则处理
        if (!"0".equals(workstation.getAncestors())) {
            // 使用 split 方法按逗号分隔字符串
            String[] items = workstation.getAncestors().split(",");
            // 将数组转换为 List
            List<String> list = Arrays.asList(items);
            List<IsWorkstation> isWorkstationList = iIsWorkstationService.list(Wrappers.<IsWorkstation>lambdaQuery()
                    .in(IsWorkstation::getWorkstationId, list));
            if (!isWorkstationList.isEmpty()) {
                List<String> collect = isWorkstationList.stream().map(IsWorkstation::getWorkstationName).collect(Collectors.toList());
                workstationName = String.join("-", collect);
            }
        }
        String sopTypeValue = DictUtils.getDictLabel("sop_type", sopType);
        String sopName = workstationName + "-" + workstation.getWorkstationName() + "-" + machinery.getMachineryName() + "-" + sopTypeValue;
        List<IsSop> listName = list(Wrappers.<IsSop>lambdaQuery()
                .eq(IsSop::getSopName, sopName)
                .ne(sopId != null, IsSop::getSopId, sopId));
        Assert.isTrue(listName.isEmpty(), "该SOP已存在!");
        return sopName;
    }

    public Boolean saveSopPoints(Long sopId, Long machineryId) {
        List<IsMachineryPoints> machineryPointsList = iIsMachineryPointsService.list(Wrappers.<IsMachineryPoints>lambdaQuery()
                .eq(IsMachineryPoints::getMachineryId, machineryId));
        if (!machineryPointsList.isEmpty()) {
            List<IsSopPoints> isSopPoints = new ArrayList<>();
            for (IsMachineryPoints isMachineryPoints : machineryPointsList) {
                IsSopPoints isSopPoint = new IsSopPoints();
                isSopPoint.setSopId(sopId);
                isSopPoint.setPointId(isMachineryPoints.getPointId());
                isSopPoints.add(isSopPoint);
                iIsSopPointsService.save(isSopPoint);
            }
            // iIsSopPointsService.saveBatch(isSopPoints);
        }
        return true;
    }

    /**
     * 批量删除SOP信息
     *
     * @param sopIds 需要删除的SOP信息主键
     * @return 结果
     */
    @Transactional
    @Override
    public Boolean deleteIsMarsSopBySopIds(String sopIds) {
        // 1.断言判断
        Assert.notBlank(sopIds, "请选择需要删除的数据!");
        // 2.删除主数据
        Long[] longIds = Convert.toLongArray(sopIds);
        isSopMapper.deleteIsSopBySopIds(longIds);
        // 3.同时删除is_sop_points关联数据
        iIsSopPointsService.remove(Wrappers.<IsSopPoints>lambdaQuery()
                .in(IsSopPoints::getSopId, longIds));
        return true;
    }


    /**
     * 删除SOP信息信息
     *
     * @param sopId SOP信息主键
     * @return 结果
     */
    @Override
    public int deleteIsMarsSopBySopId(Long sopId) {
        return isSopMapper.deleteIsSopBySopId(sopId);
    }

    @Override
    @MarsDataScope(workstationAlias = "w", userAlias = "u")
    public Page<SopPageVO> getIsMarsSopPage(PageSopDTO dto, Page<IsSop> page) {
        return isSopMapper.getIsSopPage(page, dto);
    }

    @Override
    public Boolean updateIsMarsSopIndex(IsSop isSop) {
        Assert.notNull(isSop.getSopId(), "主键id不可为空！");
        Assert.notNull(isSop.getSopIndex(), "排序数据不可为空！");
        update(Wrappers.<IsSop>lambdaUpdate()
                .eq(IsSop::getSopId, isSop.getSopId())
                .set(IsSop::getSopIndex, isSop.getSopIndex()));
        return true;
    }

    @Override
    public String importSop(List<ImportSopVO> itemList, boolean updateSupport, String operName) {
        Assert.notNull(itemList, "导入物料产品数据不能为空！");
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (ImportSopVO vo : itemList) {
            // 0.定义一个boolean，记录当前这条数据有没有问题
            boolean result = true;
            // 0.1定义一个类
            IsSop isSop = new IsSop();
            // 1.---------------SOP如果没有名称，直接返回报错--------------------
            if (StringUtils.isBlank(vo.getSopName())) {
                result = false;
                failureMsg.append("<br/>" + failureNum + "、SOP名称不可为空 ");
            }
            // 1.1检查SOP的名称是否可用
            List<IsSop> sopNameList = list(Wrappers.<IsSop>lambdaQuery()
                    .eq(IsSop::getSopName, vo.getSopName()));
            if (!sopNameList.isEmpty()) {
                result = false;
                failureMsg.append("<br/>" + failureNum + "、SOP名称 " + vo.getSopName() + " 已被使用");
            } else {
                isSop.setSopName(vo.getSopName());
            }
            // 2.-----------------检查SOP类型不能为空-------------------------------
            if (StringUtils.isNotBlank(vo.getSopType())) {
                // 2.1检查SOP类型是否在我们的系统中
                String sopType = DictUtils.getDictValue("sop_type", vo.getSopType());
                if (StringUtils.isBlank(sopType)) {
                    result = false;
                    failureMsg.append("<br/>" + failureNum + "、SOP类型 " + vo.getSopName() + " 系统中无该SOP类型");
                } else {
                    isSop.setSopType(sopType);
                }
            } else {
                result = false;
                failureMsg.append("<br/>" + failureNum + "、SOP类型 " + vo.getSopName() + " 不能为空");
            }
            // 3.-----------------检查SOP岗位不能为空-------------------------------
            if (StringUtils.isNotBlank(vo.getWorkstationName())) {
                // 3.1检查SOP岗位是否在我们的系统中
                IsWorkstation isWorkstation = iIsWorkstationService.getOne(Wrappers.<IsWorkstation>lambdaQuery()
                        .eq(IsWorkstation::getWorkstationName, vo.getWorkstationName()));
                if (isWorkstation != null) {
                    isSop.setWorkstationId(isWorkstation.getWorkstationId());
                } else {
                    result = false;
                    failureMsg.append("<br/>" + failureNum + "、SOP岗位 " + vo.getSopName() + " 系统中无该岗位");
                }
            } else {
                result = false;
                failureMsg.append("<br/>" + failureNum + "、SOP岗位 " + vo.getSopName() + " 不能为空");
            }
            // 4.-----------------检查岗位下有没有设备工艺-不能为空-------------------------------
            if (StringUtils.isNotBlank(vo.getWorkstationName())) {
                // 4.1检查设备工艺是否在我们的系统中
                IsMachinery isMachinery = isMachineryService.getOne(Wrappers.<IsMachinery>lambdaQuery()
                        .eq(IsMachinery::getWorkstationId, isSop.getWorkstationId())
                        .eq(IsMachinery::getMachineryName, vo.getMachineryName()));
                if (isMachinery != null) {
                    isSop.setMachineryId(isMachinery.getMachineryId());
                } else {
                    result = false;
                    failureMsg.append("<br/>" + failureNum + "、设备工艺 " + vo.getSopName() + " 系统岗位下无该设备工艺");
                }
            } else {
                result = false;
                failureMsg.append("<br/>" + failureNum + "、设备工艺 " + vo.getSopName() + " 不能为空");
            }
            // 开始做最后的插入操作
            if (result) {
                successNum++;
                save(isSop);
                // 3.新增隔离点和sop的关联关系
                saveSopPoints(isSop.getSopId(), isSop.getMachineryId());
            } else {
                failureNum++;
            }

        }
        // 总结
        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条");
        }
        return successMsg.toString();
    }

}
