package cn.iocoder.yudao.module.smartfactory.service.factoryinfo;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.ip.core.Area;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.smartfactory.controller.admin.factoryinfo.vo.FactoryInfoPageReqVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.factoryinfo.vo.FactoryInfoSaveReqVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.factoryinfo.vo.FactoryUpdateStatusReqVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.screendata.factory.vo.FactoryRollDataRespVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.screendata.factory.vo.ProvincesDataRespVO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.factoryinfo.FactoryInfoDO;
import cn.iocoder.yudao.module.smartfactory.dal.mysql.factoryinfo.FactoryInfoMapper;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.FACTORY_INFO_NOT_EXISTS;
import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.FACTOYRY_EXISTS_STAFF;

/**
 * 工厂信息 Service 实现类
 *
 * @author 姚君
 */
@Service
@Validated
public class FactoryInfoServiceImpl implements FactoryInfoService {

    @Resource
    private FactoryInfoMapper factoryInfoMapper;

    @Resource
    private DeptApi deptApi;

    @Resource
    private AdminUserApi userApi;

    @Resource
    private PermissionApi permissionApi;

    @Override
    public Long createFactoryInfo(FactoryInfoSaveReqVO createReqVO) {
        // 插入
        FactoryInfoDO factoryInfo = BeanUtils.toBean(createReqVO, FactoryInfoDO.class);
        factoryInfoMapper.insert(factoryInfo);

        // 新增的为工厂类型时
        if ("3".equals(createReqVO.getType())) {

            //同步插入对应 生产部的下级部门
            DeptRespDTO deptRespDTO = new DeptRespDTO();
            deptRespDTO.setFactoryId(factoryInfo.getId());
            deptRespDTO.setName(createReqVO.getShortName());
            deptRespDTO.setParentId(130L);  //这里设置上级部门为 生产部
            deptRespDTO.setLeaderUserId(createReqVO.getLeaderUserId());
            deptRespDTO.setStatus(CommonStatusEnum.ENABLE.getStatus());
            deptApi.createDept(deptRespDTO);
        }

        // 返回
        return factoryInfo.getId();
    }

    @Override
    public void updateFactoryInfo(FactoryInfoSaveReqVO updateReqVO) {
        // 校验存在
        validateFactoryInfoExists(updateReqVO.getId());
        // 更新
        FactoryInfoDO updateObj = BeanUtils.toBean(updateReqVO, FactoryInfoDO.class);
        factoryInfoMapper.updateById(updateObj);

        //同步更新 部门信息
        DeptRespDTO deptRespDTO = new DeptRespDTO();
        deptRespDTO.setName(updateReqVO.getShortName());
        deptRespDTO.setLeaderUserId(updateReqVO.getLeaderUserId());
        deptRespDTO.setFactoryId(updateReqVO.getId());
        deptApi.updateFactoryDept(deptRespDTO);
    }

    @Override
    public void deleteFactoryInfo(Long id) {
        // 校验存在
        validateFactoryInfoExists(id);

        //校验工厂下是否存在 员工
        DeptRespDTO deptRespDTO = deptApi.getDeptByFactoryId(id).getCheckedData();

        List<Long> deptId = new ArrayList<>();
        deptId.add(deptRespDTO.getId());
        List<AdminUserRespDTO> userRespDTOS = userApi.getUserListByDeptIds(deptId).getCheckedData();

        if (userRespDTOS != null && !userRespDTOS.isEmpty()) {
            throw exception(FACTOYRY_EXISTS_STAFF);
        }

        // 删除
        factoryInfoMapper.deleteById(id);

        //同步删除部门
        deptApi.deleteDept(id);
    }

    private void validateFactoryInfoExists(Long id) {
        if (factoryInfoMapper.selectById(id) == null) {
            throw exception(FACTORY_INFO_NOT_EXISTS);
        }
    }

    @Override
    public FactoryInfoDO getFactoryInfo(Long id) {

        return factoryInfoMapper.selectById(id);
    }

    @Override
    public List<FactoryInfoDO> getFactoryList() {

        return factoryInfoMapper.selectList();
    }

    @Override
    public List<FactoryInfoDO> getFactoryList(Collection<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        ids = ids.stream().filter(Objects::nonNull).collect(Collectors.toList());
        return factoryInfoMapper.selectList(new LambdaQueryWrapper<FactoryInfoDO>()
                .in(CollectionUtil.isNotEmpty(ids), FactoryInfoDO::getId, ids));
    }

    @Override
    public List<FactoryInfoDO> getFactoryList(Long factoryId, String name) {

        return factoryInfoMapper.selectList(new LambdaQueryWrapperX<FactoryInfoDO>()
                .eqIfPresent(FactoryInfoDO::getId, factoryId)
                .likeIfPresent(FactoryInfoDO::getName, name));
    }

    @Override
    public List<FactoryInfoDO> getFactoryListByType() {

        return factoryInfoMapper.selectListByType(null);
    }

    @Override
    public PageResult<FactoryInfoDO> getFactoryInfoPage(FactoryInfoPageReqVO pageReqVO) {
        return factoryInfoMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ProvincesDataRespVO> getProvincesData(String code) {
        // -- 获取当前的地区
        Area area = AreaUtils.getArea(Integer.valueOf(code));
        List<ProvincesDataRespVO> vos = new ArrayList<>();
        LambdaQueryWrapperX<FactoryInfoDO> lambdaQueryWrapperX = new LambdaQueryWrapperX<FactoryInfoDO>();
        // 只查询 type为工厂类型的 工厂信息
        lambdaQueryWrapperX.eq(FactoryInfoDO::getType, 3L);
        //去除关闭状态工厂
        lambdaQueryWrapperX.eq(FactoryInfoDO::getStatus, CommonStatusEnum.ENABLE.getStatus());

        Integer type = area.getType() - 1;
        if (!type.equals(FactoryInfoDO.ADDRESS_TYPE_NATIONWIDE)) {
            lambdaQueryWrapperX.eq(FactoryInfoDO.ADDRESS_TYPE_PROVINCE.equals(type), FactoryInfoDO::getProvinceId, code)
                    .eq(FactoryInfoDO.ADDRESS_TYPE_CITY.equals(type), FactoryInfoDO::getCityId, code)
                    .eq(FactoryInfoDO.ADDRESS_TYPE_DISTRICT_NAME.equals(type), FactoryInfoDO::getAdCode, code);
        }
        List<FactoryInfoDO> dos = factoryInfoMapper.selectList(
                lambdaQueryWrapperX
        );
        Map<Long, List<FactoryInfoDO>> map = new HashMap<>();
        if (FactoryInfoDO.ADDRESS_TYPE_NATIONWIDE.equals(type)) {
            map = dos.stream().collect(Collectors.groupingBy(FactoryInfoDO::getProvinceId));
        }
        if (FactoryInfoDO.ADDRESS_TYPE_PROVINCE.equals(type)) {
            map = dos.stream().collect(Collectors.groupingBy(FactoryInfoDO::getCityId));
        }
        if (FactoryInfoDO.ADDRESS_TYPE_CITY.equals(type)) {
            map = dos.stream().collect(Collectors.groupingBy(FactoryInfoDO::getAdCode));
        }
        if (FactoryInfoDO.ADDRESS_TYPE_DISTRICT_NAME.equals(type)) {
            map = dos.stream().collect(Collectors.groupingBy(FactoryInfoDO::getId));
        }
        for (Map.Entry<Long, List<FactoryInfoDO>> entry : map.entrySet()) {
            ProvincesDataRespVO vo = new ProvincesDataRespVO();
            vo.setAdCode(entry.getKey());
            vo.setValue(entry.getValue().size());
            vo.setVos(entry.getValue());
            vos.add(vo);
        }
        return vos;
    }

    @Override
    public List<FactoryRollDataRespVO> getFactoryRollData() {
        return factoryInfoMapper.getFactoryRollData();
    }

    @Override
    public List<FactoryInfoDO> list() {
        return factoryInfoMapper.selectList();
    }

    @Override
    public String getWeatherCodeByFactoryId(Long factoryId, String areaCode) {
        return factoryInfoMapper.getWeatherCodeByFactoryId(factoryId, areaCode);
    }

    @Override
    public List<FactoryInfoDO> getFactoryListByAuthority() {

        List<Long> factoryIds = null;
        DeptDataPermissionRespDTO deptDataPermission = permissionApi.getDeptDataPermission(getLoginUserId()).getCheckedData();
        // 如果当前登录用户数据权限 不是查看全部数据
        if (!deptDataPermission.getAll()) {

            List<DeptRespDTO> deptRespDTO = deptApi.getDeptListByLeader(getLoginUserId()).getCheckedData();

            if (deptRespDTO != null) {

                factoryIds = convertList(deptRespDTO, DeptRespDTO::getFactoryId);
            } else {

                DeptRespDTO respDTO = deptApi.getDept(userApi.getUser(getLoginUserId()).getCheckedData().getDeptId()).getCheckedData();
                factoryIds = Collections.singletonList(respDTO.getFactoryId());
            }
        }

        return factoryInfoMapper.selectListByType(factoryIds);
    }

    @Override
    public FactoryInfoDO getFactoryByName(String factoryName) {

        return factoryInfoMapper.selectOne(FactoryInfoDO::getShortName, factoryName);
    }

    @Override
    public void updateFactoryStatus(FactoryUpdateStatusReqVO updateReqVO) {
        // 校验存在
        validateFactoryInfoExists(updateReqVO.getId());

        // 更新
        FactoryInfoDO updateObj = BeanUtils.toBean(updateReqVO, FactoryInfoDO.class);
        factoryInfoMapper.updateById(updateObj);

        //同步更新 工厂部门状态
        DeptRespDTO deptRespDTO = new DeptRespDTO();
        deptRespDTO.setFactoryId(updateReqVO.getId());
        deptRespDTO.setStatus(updateReqVO.getStatus());
        deptApi.updateFactoryDept(deptRespDTO);
    }
}
