package org.dromara.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.EmployeeService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.system.domain.SysEmployee;
import org.dromara.system.domain.bo.SysEmployeeBo;
import org.dromara.system.domain.vo.SysEmployeeVo;
import org.dromara.system.mapper.SysEmployeeMapper;
import org.dromara.system.service.ISysEmployeeService;
import org.dromara.yingpaipay.api.erp.CommonErpClientService;
import org.dromara.yingpaipay.api.erp.domain.vo.CommonErpClientVo;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 员工管理 Service业务层处理
 *
 * @author Lion Li
 */
@RequiredArgsConstructor
@Service
public class SysEmployeeServiceImpl implements ISysEmployeeService, EmployeeService {

    private final SysEmployeeMapper baseMapper;
    private final CommonErpClientService commonErpClientService;

    /**
     * 查询员工
     */
    @Override
    public SysEmployeeVo queryById(Long id) {
        SysEmployeeVo vo = baseMapper.selectVoById(id);
        fillAuthClientName(vo);
        return vo;
    }

    /**
     * 查询员工详情（仅返回 authClientFRowIDs，由前端调用 ERP 接口反查客户详情）
     */
    @Override
    public SysEmployeeVo queryDetail(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 根据电话查询员工
     */
    @Override
    public SysEmployeeVo queryByPhone(String phone) {
        return baseMapper.selectVoOne(
            Wrappers.lambdaQuery(SysEmployee.class)
                .eq(SysEmployee::getPhone, phone)
        );
    }

    /**
     * 根据微信UnionID查询员工
     */
    @Override
    public SysEmployeeVo queryByWechatUnionid(String wechatUnionid) {
        return baseMapper.selectVoOne(
            Wrappers.lambdaQuery(SysEmployee.class)
                .eq(SysEmployee::getWechatUnionid, wechatUnionid)
        );
    }

    /**
     * 根据微信OpenID查询员工
     */
    @Override
    public SysEmployeeVo queryByWechatOpenid(String wechatOpenid) {
        return baseMapper.selectVoOne(
            Wrappers.lambdaQuery(SysEmployee.class)
                .eq(SysEmployee::getWechatOpenid, wechatOpenid)
        );
    }

    /**
     * 批量填充授权客户信息（列表用，逗号分隔拼接名称/类型/时间）
     */
    private void fillAuthClientName(List<SysEmployeeVo> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        List<String> allIds = list.stream()
            .map(SysEmployeeVo::getAuthClientFRowIDs)
            .filter(StringUtils::isNotBlank)
            .flatMap(ids -> Arrays.stream(ids.split(",")))
            .map(String::trim)
            .filter(StringUtils::isNotBlank)
            .distinct()
            .collect(Collectors.toList());
        if (allIds.isEmpty()) {
            return;
        }
        Map<String, CommonErpClientVo> infoMap = commonErpClientService.selectInfoByFRowIDs(allIds);
        list.forEach(vo -> {
            if (StringUtils.isBlank(vo.getAuthClientFRowIDs())) {
                return;
            }
            List<String> ids = Arrays.stream(vo.getAuthClientFRowIDs().split(","))
                .map(String::trim)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());
            List<CommonErpClientVo> clients = ids.stream()
                .map(infoMap::get)
                .filter(c -> c != null)
                .collect(Collectors.toList());
            vo.setAuthClientName(clients.stream().map(CommonErpClientVo::getName)
                .collect(Collectors.joining(" / ")));
            vo.setAuthClientClass(clients.stream().map(CommonErpClientVo::getClientClass)
                .collect(Collectors.joining(" / ")));
            vo.setAuthClientEnterDate(clients.stream()
                .map(c -> c.getEnterDate() != null ? c.getEnterDate().toString() : "")
                .collect(Collectors.joining(" / ")));
        });
    }

    /**
     * 单个填充授权客户简要信息（兼容旧逻辑）
     */
    private void fillAuthClientName(SysEmployeeVo vo) {
        if (vo == null || StringUtils.isBlank(vo.getAuthClientFRowIDs())) {
            return;
        }
        fillAuthClientName(Collections.singletonList(vo));
    }

    /**
     * 填充授权客户完整详情列表（详情弹框用）
     */
    private void fillAuthClientDetail(SysEmployeeVo vo) {
        if (vo == null || StringUtils.isBlank(vo.getAuthClientFRowIDs())) {
            vo.setAuthClientList(Collections.emptyList());
            return;
        }
        List<String> ids = Arrays.stream(vo.getAuthClientFRowIDs().split(","))
            .map(String::trim)
            .filter(StringUtils::isNotBlank)
            .collect(Collectors.toList());
        if (ids.isEmpty()) {
            vo.setAuthClientList(Collections.emptyList());
            return;
        }
        Map<String, CommonErpClientVo> infoMap = commonErpClientService.selectInfoByFRowIDs(ids);
        List<CommonErpClientVo> clients = ids.stream()
            .map(infoMap::get)
            .filter(c -> c != null)
            .collect(Collectors.toList());
        vo.setAuthClientList(clients);
    }

    /**
     * 分页查询员工列表
     */
    @Override
    public TableDataInfo<SysEmployeeVo> queryPageList(SysEmployeeBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysEmployee> lqw = buildQueryWrapper(bo);
        Page<SysEmployeeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        fillAuthClientName(result.getRecords());
        return TableDataInfo.build(result);
    }

    private LambdaQueryWrapper<SysEmployee> buildQueryWrapper(SysEmployeeBo bo) {
        LambdaQueryWrapper<SysEmployee> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getName()), SysEmployee::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), SysEmployee::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getWechatOpenid()), SysEmployee::getWechatOpenid, bo.getWechatOpenid());
        lqw.orderByDesc(SysEmployee::getId);
        return lqw;
    }

    /**
     * 新增员工
     */
    @Override
    public Boolean insertByBo(SysEmployeeBo bo) {
        SysEmployee add = MapstructUtils.convert(bo, SysEmployee.class);
        return baseMapper.insert(add) > 0;
    }

    /**
     * 修改员工（仅更新非 null 字段，支持部分更新）
     */
    @Override
    public Boolean updateByBo(SysEmployeeBo bo) {
        SysEmployee update = MapstructUtils.convert(bo, SysEmployee.class);
        LambdaUpdateWrapper<SysEmployee> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(SysEmployee::getId, update.getId());
        if (ObjectUtil.isNotNull(update.getName())) {
            wrapper.set(SysEmployee::getName, update.getName());
        }
        if (ObjectUtil.isNotNull(update.getPhone())) {
            wrapper.set(SysEmployee::getPhone, update.getPhone());
        }
        if (ObjectUtil.isNotNull(update.getAvatar())) {
            wrapper.set(SysEmployee::getAvatar, update.getAvatar());
        }
        if (ObjectUtil.isNotNull(update.getStatus())) {
            wrapper.set(SysEmployee::getStatus, update.getStatus());
        }
        if (ObjectUtil.isNotNull(update.getAuthClientFRowIDs())) {
            wrapper.set(SysEmployee::getAuthClientFRowIDs, update.getAuthClientFRowIDs());
        }
        if (ObjectUtil.isNotNull(update.getWechatOpenid())) {
            wrapper.set(SysEmployee::getWechatOpenid, update.getWechatOpenid());
        }
        if (ObjectUtil.isNotNull(update.getWechatUnionid())) {
            wrapper.set(SysEmployee::getWechatUnionid, update.getWechatUnionid());
        }
        boolean result = baseMapper.update(null, wrapper) > 0;
        if (result && bo.getId() != null) {
            CacheUtils.evict(CacheNames.SYS_EMPLOYEE_NAME, bo.getId());
        }
        return result;
    }

    /**
     * 校验授权客户是否已被其他员工占用
     */
    @Override
    public void checkAuthClientConflict(Long employeeId, String authClientFRowIDs) {
        Set<String> newRowIds = Arrays.stream(authClientFRowIDs.split(","))
            .map(String::trim)
            .filter(StringUtils::isNotBlank)
            .collect(Collectors.toSet());
        if (newRowIds.isEmpty()) {
            return;
        }
        List<SysEmployee> otherEmployees = baseMapper.selectList(
            Wrappers.lambdaQuery(SysEmployee.class)
                .select(SysEmployee::getId, SysEmployee::getAuthClientFRowIDs)
                .ne(SysEmployee::getId, employeeId)
                .isNotNull(SysEmployee::getAuthClientFRowIDs)
                .ne(SysEmployee::getAuthClientFRowIDs, "")
        );
        Set<String> conflictRowIds = new HashSet<>();
        for (SysEmployee other : otherEmployees) {
            if (StringUtils.isBlank(other.getAuthClientFRowIDs())) {
                continue;
            }
            for (String id : other.getAuthClientFRowIDs().split(",")) {
                String trimmed = id.trim();
                if (newRowIds.contains(trimmed)) {
                    conflictRowIds.add(trimmed);
                }
            }
        }
        if (conflictRowIds.isEmpty()) {
            return;
        }
        Map<String, CommonErpClientVo> infoMap = commonErpClientService.selectInfoByFRowIDs(new ArrayList<>(conflictRowIds));
        String conflictNames = conflictRowIds.stream()
            .map(id -> {
                CommonErpClientVo vo = infoMap.get(id);
                return vo != null ? vo.getName() : id;
            })
            .collect(Collectors.joining("、"));
        throw new ServiceException("以下客户已被其他员工授权，请先取消后再操作：" + conflictNames);
    }

    /**
     * 批量删除员工
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Cacheable(cacheNames = CacheNames.SYS_EMPLOYEE_NAME, key = "#employeeId")
    @Override
    public String selectNameById(Long employeeId) {
        SysEmployee employee = baseMapper.selectOne(
            Wrappers.lambdaQuery(SysEmployee.class)
                .select(SysEmployee::getName)
                .eq(SysEmployee::getId, employeeId)
        );
        return employee != null ? employee.getName() : null;
    }

    /**
     * 修改员工状态（启用/禁用）
     */
    @Override
    public Boolean changeStatus(Long id, String status) {
        SysEmployee employee = baseMapper.selectById(id);
        if (employee == null) {
            throw new ServiceException("员工不存在");
        }
        employee.setStatus(status);
        return baseMapper.updateById(employee) > 0;
    }
}
