package com.ruoyi.ccdi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.domain.CcdiEmployee;
import com.ruoyi.ccdi.domain.CcdiEmployeeRelative;
import com.ruoyi.ccdi.domain.dto.CcdiEmployeeAddDTO;
import com.ruoyi.ccdi.domain.dto.CcdiEmployeeEditDTO;
import com.ruoyi.ccdi.domain.dto.CcdiEmployeeQueryDTO;
import com.ruoyi.ccdi.domain.dto.CcdiEmployeeRelativeAddDTO;
import com.ruoyi.ccdi.domain.excel.CcdiEmployeeExcel;
import com.ruoyi.ccdi.domain.vo.CcdiEmployeeVO;
import com.ruoyi.ccdi.enums.EmployeeStatus;
import com.ruoyi.ccdi.mapper.CcdiEmployeeMapper;
import com.ruoyi.ccdi.mapper.CcdiEmployeeRelativeMapper;
import com.ruoyi.ccdi.service.ICcdiEmployeeService;
import com.ruoyi.common.utils.IdCardUtil;
import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 员工信息 服务层处理
 *
 * @author ruoyi
 * @date 2026-01-28
 */
@Service
public class CcdiEmployeeServiceImpl implements ICcdiEmployeeService {

    @Resource
    private CcdiEmployeeMapper employeeMapper;

    @Resource
    private CcdiEmployeeRelativeMapper relativeMapper;

    /**
     * 查询员工列表
     *
     * @param queryDTO 查询条件
     * @return 员工VO集合
     */
    @Override
    public List<CcdiEmployeeVO> selectEmployeeList(CcdiEmployeeQueryDTO queryDTO) {
        LambdaQueryWrapper<CcdiEmployee> wrapper = buildQueryWrapper(queryDTO);
        List<CcdiEmployee> list = employeeMapper.selectList(wrapper);
        List<CcdiEmployeeVO> voList = new ArrayList<>();
        for (CcdiEmployee employee : list) {
            voList.add(convertToVO(employee));
        }
        return voList;
    }

    /**
     * 分页查询员工列表
     *
     * @param page     分页对象
     * @param queryDTO 查询条件
     * @return 员工VO分页结果
     */
    @Override
    public Page<CcdiEmployeeVO> selectEmployeePage(Page<CcdiEmployeeVO> page, CcdiEmployeeQueryDTO queryDTO) {
        // 使用关联查询获取部门名称
        Page<CcdiEmployeeVO> voPage = new Page<>(page.getCurrent(), page.getSize());
        Page<CcdiEmployeeVO> resultPage = employeeMapper.selectEmployeePageWithDept(voPage, queryDTO);

        // 设置状态描述
        resultPage.getRecords().forEach(vo ->
            vo.setStatusDesc(EmployeeStatus.getDescByCode(vo.getStatus()))
        );

        return resultPage;
    }

    /**
     * 查询员工列表（用于导出）
     *
     * @param queryDTO 查询条件
     * @return 员工Excel实体集合
     */
    @Override
    public List<CcdiEmployeeExcel> selectEmployeeListForExport(CcdiEmployeeQueryDTO queryDTO) {
        LambdaQueryWrapper<CcdiEmployee> wrapper = buildQueryWrapper(queryDTO);
        List<CcdiEmployee> list = employeeMapper.selectList(wrapper);
        return list.stream().map(employee -> {
            CcdiEmployeeExcel excel = new CcdiEmployeeExcel();
            BeanUtils.copyProperties(employee, excel);
            return excel;
        }).toList();
    }

    /**
     * 查询员工详情
     *
     * @param employeeId 员工ID
     * @return 员工VO
     */
    @Override
    public CcdiEmployeeVO selectEmployeeById(Long employeeId) {
        return employeeMapper.selectEmployeeWithRelatives(employeeId);
    }

    /**
     * 新增员工
     *
     * @param addDTO 新增DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int insertEmployee(CcdiEmployeeAddDTO addDTO) {
        // 检查柜员号唯一性
        LambdaQueryWrapper<CcdiEmployee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiEmployee::getTellerNo, addDTO.getTellerNo());
        if (employeeMapper.selectCount(wrapper) > 0) {
            throw new RuntimeException("该柜员号已存在");
        }

        // 检查身份证号唯一性
        wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiEmployee::getIdCard, addDTO.getIdCard());
        if (employeeMapper.selectCount(wrapper) > 0) {
            throw new RuntimeException("该身份证号已存在");
        }

        CcdiEmployee employee = new CcdiEmployee();
        BeanUtils.copyProperties(addDTO, employee);
        int result = employeeMapper.insert(employee);

        // 插入亲属信息
        if (addDTO.getRelatives() != null && !addDTO.getRelatives().isEmpty()) {
            for (CcdiEmployeeRelativeAddDTO relativeAddDTO : addDTO.getRelatives()) {
                CcdiEmployeeRelative relative = new CcdiEmployeeRelative();
                BeanUtils.copyProperties(relativeAddDTO, relative);
                relative.setEmployeeId(employee.getEmployeeId());
                relativeMapper.insert(relative);
            }
        }

        return result;
    }

    /**
     * 修改员工
     *
     * @param editDTO 编辑DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int updateEmployee(CcdiEmployeeEditDTO editDTO) {
        // 检查柜员号唯一性（排除自己）
        if (StringUtils.isNotEmpty(editDTO.getTellerNo())) {
            LambdaQueryWrapper<CcdiEmployee> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CcdiEmployee::getTellerNo, editDTO.getTellerNo())
                    .ne(CcdiEmployee::getEmployeeId, editDTO.getEmployeeId());
            if (employeeMapper.selectCount(wrapper) > 0) {
                throw new RuntimeException("该柜员号已存在");
            }
        }

        // 检查身份证号唯一性（排除自己）
        if (StringUtils.isNotEmpty(editDTO.getIdCard())) {
            LambdaQueryWrapper<CcdiEmployee> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CcdiEmployee::getIdCard, editDTO.getIdCard())
                    .ne(CcdiEmployee::getEmployeeId, editDTO.getEmployeeId());
            if (employeeMapper.selectCount(wrapper) > 0) {
                throw new RuntimeException("该身份证号已存在");
            }
        }

        CcdiEmployee employee = new CcdiEmployee();
        BeanUtils.copyProperties(editDTO, employee);
        int result = employeeMapper.updateById(employee);

        // 删除原有亲属信息
        LambdaQueryWrapper<CcdiEmployeeRelative> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiEmployeeRelative::getEmployeeId, editDTO.getEmployeeId());
        relativeMapper.delete(wrapper);

        // 插入新的亲属信息
        if (editDTO.getRelatives() != null && !editDTO.getRelatives().isEmpty()) {
            for (CcdiEmployeeRelativeAddDTO relativeAddDTO : editDTO.getRelatives()) {
                CcdiEmployeeRelative relative = new CcdiEmployeeRelative();
                BeanUtils.copyProperties(relativeAddDTO, relative);
                relative.setEmployeeId(editDTO.getEmployeeId());
                relativeMapper.insert(relative);
            }
        }

        return result;
    }

    /**
     * 批量删除员工
     *
     * @param employeeIds 需要删除的员工ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteEmployeeByIds(Long[] employeeIds) {
        // 级联删除亲属信息
        for (Long employeeId : employeeIds) {
            LambdaQueryWrapper<CcdiEmployeeRelative> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CcdiEmployeeRelative::getEmployeeId, employeeId);
            relativeMapper.delete(wrapper);
        }
        return employeeMapper.deleteBatchIds(List.of(employeeIds));
    }

    /**
     * 导入员工数据
     *
     * @param excelList     Excel实体列表
     * @param isUpdateSupport 是否更新支持
     * @return 结果
     */
    @Override
    @Transactional
    public String importEmployee(List<CcdiEmployeeExcel> excelList, Boolean isUpdateSupport) {
        if (StringUtils.isNull(excelList) || excelList.isEmpty()) {
            return "至少需要一条数据";
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        for (CcdiEmployeeExcel excel : excelList) {
            try {
                // 转换为AddDTO
                CcdiEmployeeAddDTO addDTO = new CcdiEmployeeAddDTO();
                BeanUtils.copyProperties(excel, addDTO);

                // 验证数据
                validateEmployeeData(addDTO, isUpdateSupport);

                CcdiEmployee employee = new CcdiEmployee();
                BeanUtils.copyProperties(addDTO, employee);

                employeeMapper.insert(employee);
                successNum++;
                successMsg.append("<br/>").append(successNum).append("、").append(addDTO.getName()).append(" 导入成功");
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("、").append(excel.getName()).append(" 导入失败：");
                failureMsg.append(e.getMessage());
            }
        }

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

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<CcdiEmployee> buildQueryWrapper(CcdiEmployeeQueryDTO queryDTO) {
        LambdaQueryWrapper<CcdiEmployee> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotEmpty(queryDTO.getName()), CcdiEmployee::getName, queryDTO.getName())
                .eq(StringUtils.isNotEmpty(queryDTO.getTellerNo()), CcdiEmployee::getTellerNo, queryDTO.getTellerNo())
                .eq(queryDTO.getDeptId() != null, CcdiEmployee::getDeptId, queryDTO.getDeptId())
                .like(StringUtils.isNotEmpty(queryDTO.getIdCard()), CcdiEmployee::getIdCard, queryDTO.getIdCard())
                .eq(StringUtils.isNotEmpty(queryDTO.getStatus()), CcdiEmployee::getStatus, queryDTO.getStatus())
                .orderByDesc(CcdiEmployee::getCreateTime);
        return wrapper;
    }

    /**
     * 验证员工数据
     */
    private void validateEmployeeData(CcdiEmployeeAddDTO addDTO, Boolean isUpdateSupport) {
        // 验证必填字段
        if (StringUtils.isEmpty(addDTO.getName())) {
            throw new RuntimeException("姓名不能为空");
        }
        if (StringUtils.isEmpty(addDTO.getTellerNo())) {
            throw new RuntimeException("柜员号不能为空");
        }
        if (StringUtils.isEmpty(addDTO.getIdCard())) {
            throw new RuntimeException("身份证号不能为空");
        }
        if (StringUtils.isEmpty(addDTO.getStatus())) {
            throw new RuntimeException("状态不能为空");
        }

        // 验证身份证号格式
        String idCardError = IdCardUtil.getErrorMessage(addDTO.getIdCard());
        if (idCardError != null) {
            throw new RuntimeException(idCardError);
        }

        // 检查柜员号唯一性
        LambdaQueryWrapper<CcdiEmployee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiEmployee::getTellerNo, addDTO.getTellerNo());
        if (employeeMapper.selectCount(wrapper) > 0) {
            throw new RuntimeException("该柜员号已存在");
        }

        // 检查身份证号唯一性
        wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiEmployee::getIdCard, addDTO.getIdCard());
        if (employeeMapper.selectCount(wrapper) > 0) {
            throw new RuntimeException("该身份证号已存在");
        }

        // 验证状态
        if (!"0".equals(addDTO.getStatus()) && !"1".equals(addDTO.getStatus())) {
            throw new RuntimeException("状态只能填写'在职'或'离职'");
        }
    }

    /**
     * 转换为VO对象
     */
    private CcdiEmployeeVO convertToVO(CcdiEmployee employee) {
        if (employee == null) {
            return null;
        }

        CcdiEmployeeVO vo = new CcdiEmployeeVO();
        BeanUtils.copyProperties(employee, vo);
        vo.setStatusDesc(EmployeeStatus.getDescByCode(employee.getStatus()));
        return vo;
    }
}
