package cn.iocoder.yudao.module.employee.service.info;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.employee.controller.admin.info.vo.EmployeeInfoHistorySaveReqVO;
import cn.iocoder.yudao.module.employee.controller.admin.info.vo.EmployeeInfoPageReqVO;
import cn.iocoder.yudao.module.employee.controller.admin.info.vo.EmployeeInfoQueryReqVO;
import cn.iocoder.yudao.module.employee.controller.admin.info.vo.EmployeeInfoSaveReqVO;
import cn.iocoder.yudao.module.employee.dal.dataobject.info.EmployeeInfoDO;
import cn.iocoder.yudao.module.employee.dal.mysql.info.EmployeeInfoMapper;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
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.module.employee.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.POST_NOT_FOUND;

/**
 * 员工信息 Service 实现类
 *
 * @author zhaopq
 */
@Service
@Validated
public class EmployeeInfoServiceImpl implements EmployeeInfoService {

    private static final Logger log = LoggerFactory.getLogger(EmployeeInfoServiceImpl.class);
    @Resource
    private EmployeeInfoMapper infoMapper;
    @Resource
    private EmployeeInfoHistoryService employeeInfoHistoryService;

    @Resource
    private DeptService deptService;

    @Resource
    private PostService postService;

    @Override
    public List<EmployeeInfoDO> getEmployeeListByIds(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return infoMapper.selectBatchIds(ids);
    }

    @Override
    public EmployeeInfoDO getEmployeeByUserId(Long userId) {
        // 检查用户ID是否为空
        // 如果用户ID为空，则不执行任何操作，返回null
        if (userId == null) {
            return null;
        }

        // 创建查询包装器，用于查询特定用户ID的员工信息
        LambdaQueryWrapper<EmployeeInfoDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EmployeeInfoDO::getUserId, userId);
        // 使用包装器查询员工信息
        EmployeeInfoDO employeeInfoDO = infoMapper.selectOne(lambdaQueryWrapper);
        // 检查员工信息对象是否为空
        if (employeeInfoDO == null) {
            // 如果为空，则返回null，表示无法继续处理
            return null;
        }

        // 如果部门ID不为空，则尝试获取部门详细信息
        Long deptId = employeeInfoDO.getDeptId();
        if (deptId != null) {
            DeptDO dept = deptService.getDept(deptId);
            // 如果成功获取到部门信息，则设置部门名称到员工信息中
            if (dept != null) {
                employeeInfoDO.setDeptName(dept.getName());
            }
        }

        // 如果职位ID不为空，则尝试获取职位详细信息
        Long postId = employeeInfoDO.getPostId();
        if (postId != null) {
            PostDO post = postService.getPost(postId);
            // 如果成功获取到职位信息，则设置职位名称到员工信息中
            if (post != null) {
                employeeInfoDO.setPosition(post.getName());
            }
        }
        // 返回查询到的员工信息
        return employeeInfoDO;
    }

    @Override
    public List<EmployeeInfoDO> getInfoListByUserIds(Collection<Long> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<EmployeeInfoDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(EmployeeInfoDO::getUserId, userIds);
        List<EmployeeInfoDO> employeeInfoDOList = infoMapper.selectList(lambdaQueryWrapper);

        // 拼接数据
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(employeeInfoDOList, EmployeeInfoDO::getDeptId));
        List<Long> postIdList = employeeInfoDOList.stream().map(EmployeeInfoDO::getPostId).collect(Collectors.toList());
        List<PostDO> postList = postService.getPostList(postIdList);
        Map<Long, PostDO> postMap = CollectionUtils.convertMap(postList, PostDO::getId);
        for (EmployeeInfoDO employeeInfoDO : employeeInfoDOList) {
            DeptDO deptDO = deptMap.get(employeeInfoDO.getDeptId());
            if (deptDO != null) {
                employeeInfoDO.setDeptName(deptDO.getName());
            }
            PostDO postDO = postMap.get(employeeInfoDO.getPostId());
            if (postDO != null) {
                employeeInfoDO.setPosition(postDO.getName());
            }
        }

        return employeeInfoDOList;
    }

    @Override
    public Long createInfo(EmployeeInfoSaveReqVO createReqVO) {
        // 插入
        if(createReqVO.getPostId() != null) {
            PostDO post = postService.getPost(createReqVO.getPostId());
            if (post == null) {
                throw exception(POST_NOT_FOUND);
            }
            createReqVO.setPosition(post.getName());
        }
        // 部门
        if (createReqVO.getDeptId() != null) {
            DeptDO dept = deptService.getDept(createReqVO.getDeptId());
            if (dept != null && StringUtils.isNotBlank(dept.getName())) {
                createReqVO.setDeptName(dept.getName());
            }
        }
        // 检查电话号码是否为空
        if (createReqVO.getPhone() == null || createReqVO.getPhone().isEmpty()) {
            throw exception(EMPLOYEE_INFO_PHONE_NOT_NULL);
        }
        // 手机号+租户判重
        EmployeeInfoQueryReqVO reqVO = new EmployeeInfoQueryReqVO();
        reqVO.setPhone(createReqVO.getPhone());
        reqVO.setTenantId(createReqVO.getTenantId());
        EmployeeInfoDO employeeInfoDO = this.getInfo(reqVO);
        if (employeeInfoDO != null) {
            throw exception(EMPLOYEE_INFO_PHONE_EXISTS);
        }
        // 获取用户信息和租户ID
//        LoginUser user = SecurityFrameworkUtils.getLoginUser();
//        if (createReqVO.getTenantId() == null) {
//            Long tenantId = user != null && user.getTenantId() != null ? user.getTenantId() : 0L;
//            createReqVO.setTenantId(tenantId);
//        }
        if (createReqVO.getBaseAnnualLeave() == null) {
            createReqVO.setBaseAnnualLeave(BigDecimal.ZERO);
        }
        createReqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
        createReqVO.setUsedAnnualLeave(BigDecimal.ZERO);
        if (createReqVO.getBaseAnnualLeave() != null && createReqVO.getUsedAnnualLeave() != null) {
            createReqVO.setRemainingAnnualLeave(createReqVO.getBaseAnnualLeave().subtract(createReqVO.getUsedAnnualLeave()));
        }
        // 生成id
        createReqVO.setInfoId(IdUtil.fastSimpleUUID());
        EmployeeInfoDO info = BeanUtils.toBean(createReqVO, EmployeeInfoDO.class);
        infoMapper.insert(info);
        // 返回
        return info.getId();
    }

    @Override
    @TenantIgnore
    public Integer updateInfo(EmployeeInfoSaveReqVO updateReqVO) {
        // 校验存在
        validateInfoExists(updateReqVO.getId());
        EmployeeInfoDO employeeInfoDO = this.getInfo(updateReqVO.getId());
        if (employeeInfoDO == null) {
            throw exception(EMPLOYEE_INFO_NOT_EXISTS);
        }
        // 获取用户信息和租户ID
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        Long tenantId = user != null && user.getTenantId() != null ? user.getTenantId() : 0L;

        // 假设 employeeInfoDO 和 updateReqVO 已经被正确定义和初始化
        String newPhone = updateReqVO.getPhone();
        String currentPhone = employeeInfoDO.getPhone();
        // 部门
        if (updateReqVO.getDeptId() != null) {
            DeptDO dept = deptService.getDept(updateReqVO.getDeptId());
            if (dept != null && StringUtils.isNotBlank(dept.getName())) {
                updateReqVO.setDeptName(dept.getName());
            }
        }
        // 检查新电话号码是否为空
        if (newPhone == null || newPhone.isEmpty()) {
            throw exception(EMPLOYEE_INFO_PHONE_NOT_NULL);
        }

        // 如果新电话号码不为空，且与当前电话号码不同，则进行判重检查
        if (!newPhone.equals(currentPhone)) {
            // 手机号+租户判重
            EmployeeInfoQueryReqVO reqVO = new EmployeeInfoQueryReqVO();
            reqVO.setPhone(newPhone);
            reqVO.setTenantId(tenantId);
            EmployeeInfoDO infoDO = this.getInfo(reqVO);
            if (infoDO != null) {
                // 如果找到了相同的电话号码和租户ID，则抛出异常
                throw exception(EMPLOYEE_INFO_PHONE_EXISTS);
            }
        }

        EmployeeInfoHistorySaveReqVO historySaveReqVO = BeanUtils.toBean(employeeInfoDO, EmployeeInfoHistorySaveReqVO.class);
        historySaveReqVO.setEmployeeId(employeeInfoDO.getId());
        historySaveReqVO.setId(null);
        employeeInfoHistoryService.createInfoHistory(historySaveReqVO);// 插入历史数据
        // 更新
        if(updateReqVO.getPostId() != null) {
            PostDO post = postService.getPost(updateReqVO.getPostId());
            if (post == null) {
                throw exception(POST_NOT_FOUND);
            }
            updateReqVO.setPosition(post.getName());
        }
        if (updateReqVO.getBaseAnnualLeave() != null) {
            updateReqVO.setRemainingAnnualLeave(updateReqVO.getBaseAnnualLeave().subtract(employeeInfoDO.getUsedAnnualLeave()));
        }
        EmployeeInfoDO updateObj = BeanUtils.toBean(updateReqVO, EmployeeInfoDO.class);
        return infoMapper.updateById(updateObj);
    }

    @Override
    public void deleteInfo(Long id) {
        // 校验存在
        validateInfoExists(id);
        // 删除
        infoMapper.deleteById(id);
    }

    private void validateInfoExists(Long id) {
        if (infoMapper.selectById(id) == null) {
            throw exception(EMPLOYEE_INFO_NOT_EXISTS);
        }
    }

    @Override
    public EmployeeInfoDO getInfo(Long id) {
        return infoMapper.selectById(id);
    }

    @Override
    public EmployeeInfoDO getLoginEmployee() {
        // 获取当前登录用户的身份ID
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        // 根据用户身份ID查询员工信息
        EmployeeInfoDO employeeInfoDO = infoMapper.selectOne(EmployeeInfoDO::getUserId, loginUserId);
        // 如果员工信息不存在，则抛出异常
        if (employeeInfoDO == null) {
            throw exception(EMPLOYEE_INFO_NOT_EXISTS);
        }
        // 返回查询到的员工信息
        return employeeInfoDO;
    }

    @Override
    public PageResult<EmployeeInfoDO> getInfoPage(EmployeeInfoPageReqVO pageReqVO) {
        return infoMapper.selectPage(pageReqVO);
    }

    @Override
    public List<EmployeeInfoDO> getInfoListForSelectEmployee(String auth, String name, Long deptId, String phone) {
        LambdaQueryWrapper<EmployeeInfoDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(name)) {
            lambdaQueryWrapper.like(EmployeeInfoDO::getName, name);
        }
        if (deptId != null) {
            lambdaQueryWrapper.eq(EmployeeInfoDO::getDeptId, deptId);
        }
        if (StrUtil.isNotBlank(phone)) {
            lambdaQueryWrapper.like(EmployeeInfoDO::getPhone, phone);
        }
        List<EmployeeInfoDO> employeeInfoDOList = infoMapper.selectList(lambdaQueryWrapper);
        if (CollUtil.isEmpty(employeeInfoDOList)) {
            return Collections.emptyList();
        }
        return employeeInfoDOList;
    }

    @Override
    @TenantIgnore
    public EmployeeInfoDO getInfoByUserIdAndTenantId(Long userId, Long tenantId) {
        LambdaQueryWrapper<EmployeeInfoDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EmployeeInfoDO::getUserId, userId)
                .eq(EmployeeInfoDO::getTenantId, tenantId);
        return infoMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    @TenantIgnore
    public EmployeeInfoDO getInfo(EmployeeInfoQueryReqVO queryReqVO) {
        return infoMapper.getInfo(queryReqVO);
    }

}