package org.dromara.personnel.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.PhoneUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.personnel.domain.OpsUserFiles;
import org.dromara.personnel.domain.OpsWorkWage;
import org.dromara.personnel.mapper.OpsWorkWageMapper;
import org.dromara.personnel.service.IOpsUserFilesService;
import org.dromara.personnel.service.IOpsWorkWageService;
import org.dromara.system.api.RemoteProjectService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.vo.RemoteUserVo;
import org.dromara.system.api.utils.IdCardEncryptorUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.personnel.domain.bo.OpsUserBo;
import org.dromara.personnel.domain.vo.OpsUserVo;
import org.dromara.personnel.domain.OpsUser;
import org.dromara.personnel.mapper.OpsUserMapper;
import org.dromara.personnel.service.IOpsUserService;

import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 运维人员Service业务层处理
 *
 * @author LionLi
 * @date 2025-09-16
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OpsUserServiceImpl extends ServiceImpl<OpsUserMapper, OpsUser> implements IOpsUserService {

    private final OpsUserMapper baseMapper;

    @Autowired
    private RemoteProjectService remoteProjectService;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private IdCardEncryptorUtil idCardEncryptorUtil;

    @Autowired
    private IOpsWorkWageService opsWorkWageService;
    @Autowired
    private IOpsUserFilesService opsUserFilesService;

    /**
     * 查询运维人员
     *
     * @param id 主键
     * @return 运维人员
     */
    @Override
    public OpsUserVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询运维人员列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 运维人员分页列表
     */
    @Override
    public TableDataInfo<OpsUserVo> queryPageList(OpsUserBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<OpsUser> lqw = buildQueryWrapper(bo);
        Page<OpsUserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的运维人员列表
     *
     * @param bo 查询条件
     * @return 运维人员列表
     */
    @Override
    public List<OpsUserVo> queryList(OpsUserBo bo) {
        LambdaQueryWrapper<OpsUser> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OpsUser> buildQueryWrapper(OpsUserBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OpsUser> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(OpsUser::getId);
        lqw.eq(StringUtils.isNotBlank(bo.getFacePic()), OpsUser::getFacePic, bo.getFacePic());
        lqw.eq(bo.getSysUserId() != null, OpsUser::getSysUserId, bo.getSysUserId());
        lqw.like(StringUtils.isNotBlank(bo.getUserName()), OpsUser::getUserName, bo.getUserName());
        lqw.eq(bo.getProjectId() != null, OpsUser::getProjectId, bo.getProjectId());
        lqw.eq(bo.getTeamId() != null, OpsUser::getTeamId, bo.getTeamId());
        lqw.like(StringUtils.isNotBlank(bo.getTeamName()), OpsUser::getTeamName, bo.getTeamName());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), OpsUser::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), OpsUser::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getSex()), OpsUser::getSex, bo.getSex());
        lqw.eq(StringUtils.isNotBlank(bo.getNation()), OpsUser::getNation, bo.getNation());
        lqw.eq(StringUtils.isNotBlank(bo.getSfzFrontPic()), OpsUser::getSfzFrontPic, bo.getSfzFrontPic());
        lqw.eq(StringUtils.isNotBlank(bo.getSfzBackPic()), OpsUser::getSfzBackPic, bo.getSfzBackPic());
        lqw.eq(StringUtils.isNotBlank(bo.getSfzNumber()), OpsUser::getSfzNumber, bo.getSfzNumber());
        lqw.eq(bo.getSfzStart() != null, OpsUser::getSfzStart, bo.getSfzStart());
        lqw.eq(bo.getSfzEnd() != null, OpsUser::getSfzEnd, bo.getSfzEnd());
        lqw.eq(StringUtils.isNotBlank(bo.getSfzSite()), OpsUser::getSfzSite, bo.getSfzSite());
        lqw.eq(bo.getSfzBirth() != null, OpsUser::getSfzBirth, bo.getSfzBirth());
        lqw.eq(StringUtils.isNotBlank(bo.getNativePlace()), OpsUser::getNativePlace, bo.getNativePlace());
        lqw.eq(StringUtils.isNotBlank(bo.getYhkPic()), OpsUser::getYhkPic, bo.getYhkPic());
        lqw.eq(StringUtils.isNotBlank(bo.getYhkNumber()), OpsUser::getYhkNumber, bo.getYhkNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getYhkOpeningBank()), OpsUser::getYhkOpeningBank, bo.getYhkOpeningBank());
        lqw.eq(StringUtils.isNotBlank(bo.getYhkCardholder()), OpsUser::getYhkCardholder, bo.getYhkCardholder());
        lqw.eq(StringUtils.isNotBlank(bo.getTypeOfWork()), OpsUser::getTypeOfWork, bo.getTypeOfWork());
        lqw.eq(StringUtils.isNotBlank(bo.getWageMeasureUnit()), OpsUser::getWageMeasureUnit, bo.getWageMeasureUnit());
        lqw.eq(StringUtils.isNotBlank(bo.getSpecialWorkPic()), OpsUser::getSpecialWorkPic, bo.getSpecialWorkPic());
        lqw.eq(StringUtils.isNotBlank(bo.getClock()), OpsUser::getClock, bo.getClock());
        lqw.eq(StringUtils.isNotBlank(bo.getEntryDate()), OpsUser::getEntryDate, bo.getEntryDate());
        lqw.eq(StringUtils.isNotBlank(bo.getLeaveDate()), OpsUser::getLeaveDate, bo.getLeaveDate());
        lqw.eq(bo.getSalary() != null, OpsUser::getSalary, bo.getSalary());
        lqw.eq(StringUtils.isNotBlank(bo.getUserRole()), OpsUser::getUserRole, bo.getUserRole());
        lqw.eq(StringUtils.isNotBlank(bo.getExitStatus()), OpsUser::getExitStatus, bo.getExitStatus());
        lqw.eq(bo.getFirstDate() != null, OpsUser::getFirstDate, bo.getFirstDate());
        return lqw;
    }

    /**
     * 新增运维人员
     *
     * @param bo 运维人员
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(OpsUserBo bo) {
        OpsUser add = MapstructUtils.convert(bo, OpsUser.class);
        validEntityBeforeSave(add, true);
        Long userId = LoginHelper.getUserId();
        remoteProjectService.validAuth(bo.getProjectId(), userId);
        String phone = add.getPhone();
        RemoteUserVo userVo = remoteUserService.selectUserByPhonenumber(phone);
        if (userVo == null) {
            throw new ServiceException("当前用户未在系统注册", HttpStatus.BAD_REQUEST);
        }
        add.setSysUserId(userVo.getUserId());
        String encrypt = idCardEncryptorUtil.encrypt(bo.getSfzNumber());
        add.setSfzNumber(encrypt);

        boolean flag = baseMapper.insert(add) > 0;
        if (!flag) {
            throw new ServiceException("新增施工人员失败，数据库异常", HttpStatus.ERROR);
        }
        bo.setId(add.getId());
        return flag;
    }

    /**
     * 修改运维人员
     *
     * @param bo 运维人员
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(OpsUserBo bo) {
        OpsUser update = MapstructUtils.convert(bo, OpsUser.class);
        validEntityBeforeSave(update, false);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OpsUser entity, Boolean create) {
        //TODO 做一些数据校验,如唯一约束
        // 校验项目id和对应项目是否存在
        Long projectId = entity.getProjectId();
        // 校验分包公司id和对应项目是否存在
        String typeOfWork = entity.getTypeOfWork();
        String wageMeasureUnit = entity.getWageMeasureUnit();
        String phone = entity.getPhone();
        String sfzNumber = entity.getSfzNumber();
        if (projectId == null) {
            throw new ServiceException("项目 id 不能为空", HttpStatus.BAD_REQUEST);
        }

        if (remoteProjectService.getById(projectId) == null) {
            throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
        }
        if (StringUtils.isNotEmpty(wageMeasureUnit) && StringUtils.isNotEmpty(typeOfWork)) {
            LambdaQueryWrapper<OpsWorkWage> lqw = Wrappers.lambdaQuery(OpsWorkWage.class)
                .eq(OpsWorkWage::getProjectId, projectId)
                .eq(OpsWorkWage::getWorkType, typeOfWork)
                .eq(OpsWorkWage::getWageMeasureUnit, wageMeasureUnit);
            long count = opsWorkWageService.getBaseMapper().selectCount(lqw);
            if (count <= 0) {
                throw new ServiceException("当前工种没有定义工资标准，请前往工种薪水设置进行设置后再选择", HttpStatus.BAD_REQUEST);
            }
        }
        if (StringUtils.isNotEmpty(phone) && !PhoneUtil.isPhone(phone)) {
            throw new ServiceException("手机号码格式不正确", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isNotEmpty(sfzNumber) && !IdcardUtil.isValidCard(sfzNumber)) {
            throw new ServiceException("身份证号码格式不正确", HttpStatus.BAD_REQUEST);
        }
    }

    /**
     * 校验并批量删除运维人员信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {

        //TODO 做一些业务上的校验,判断是否需要校验
        Long userId = LoginHelper.getUserId();
        List<OpsUser> constructionUserList = this.listByIds(ids);
        if (isValid) {
            // 做一些业务上的校验,判断是否需要校验
            // 获取项目id列表
            List<Long> projectIdList = constructionUserList.stream().map(OpsUser::getProjectId).toList();
            // 判断是否有权限操作对应项目下的内容
            remoteProjectService.validAuth(projectIdList, userId);
            // 判断待删除的人员是否存在于班组
//                LambdaQueryWrapper<BusProjectTeamMember> projectTeamMemberLqw = Wrappers.lambdaQuery(BusProjectTeamMember.class)
//                    .in(BusProjectTeamMember::getMemberId, ids);
//                if (projectTeamMemberService.count(projectTeamMemberLqw) > 0) {
//                    throw new ServiceException("删除施工人员信息失败，施工人员存在于班组中", HttpStatus.BAD_REQUEST);
//                }
        }
        // 判断对应数据是否都存在
        if (constructionUserList.size() != ids.size()) {
            throw new ServiceException("删除施工人员信息失败，数据缺失", HttpStatus.BAD_REQUEST);
        }
        // 批量删除施工人员下的文件信息
        LambdaQueryWrapper<OpsUserFiles> constructionUserFileLqw = Wrappers.lambdaQuery(OpsUserFiles.class)
            .in(OpsUserFiles::getOpsUserId, ids);
        List<OpsUserFiles> fileList = opsUserFilesService.list(constructionUserFileLqw);
        if (CollUtil.isNotEmpty(fileList)) {
            boolean removeFile = opsUserFilesService.remove(constructionUserFileLqw);
            if (!removeFile) {
                throw new ServiceException("删除施工人员信息失败，施工人员文件信息删除失败", HttpStatus.ERROR);
            }
        }

        return baseMapper.deleteByIds(ids) > 0;
    }
}
