package org.dromara.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.dto.StaffManageDTO;
import org.dromara.common.core.utils.DateUtils;
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.RedisUtils;
import org.dromara.domain.staffTrain.StaffTrainManual;
import org.dromara.domain.staffTrain.bo.StaffTrainManualBo;
import org.dromara.domain.staffTrain.vo.StaffTrainManualVo;
import org.dromara.mapper.StaffTrainManualMapper;
import org.dromara.service.IStaffTrainManualService;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static org.dromara.common.core.constant.Constants.READ_TRAIN;
import static org.dromara.common.core.constant.Constants.READ_TRAIN_TIME;
import static org.dromara.common.satoken.utils.LoginHelper.getLoginUser;
import static org.dromara.common.satoken.utils.LoginHelper.getUserId;

/**
 * 员工培训手册Service业务层处理
 *
 * @author boman
 * @date 2025-04-11
 */
@RequiredArgsConstructor
@Service
public class StaffTrainManualServiceImpl implements IStaffTrainManualService {

    private final StaffTrainManualMapper baseMapper;

    /**
     * 查询员工培训手册
     *
     * @param manualId 主键
     * @return 员工培训手册
     */
    @Override
    public StaffTrainManualVo queryById(Long manualId){
        //获取该培训手册对象阅读人员的value值
        List<String> valueList = RedisUtils.getCacheList(READ_TRAIN + manualId);
        //获取当前登录人的员工信息
        StaffManageDTO staffManage = getLoginUser().getStaffManage();
        Long userId = getUserId();
        //获取员工姓名
        String staffName = "未知";
        if (staffManage != null) {
            staffName = staffManage.getStaffName();
        }
        //组装value值
        String value = userId + ":" + staffName;
        if (valueList != null && valueList.size() > 0) {
            //如果value不重复则新增
            if (!valueList.contains(value)) {
                //阅读名单存储到redis key = read_train:manualId value = userId+":"+员工姓名
                valueList.add(value);
                RedisUtils.deleteObject(READ_TRAIN + manualId);
                RedisUtils.setCacheList(READ_TRAIN + manualId, valueList);
                //新增阅读时间
                //key = read_train_time:manualId:userId
                RedisUtils.setCacheObject(READ_TRAIN_TIME + manualId + ":" + userId, DateUtils.getTime());
            }else {
                //更新阅读时间
                //key = read_train_time:manualId:userId
                RedisUtils.setCacheObject(READ_TRAIN_TIME + manualId + ":" + userId, DateUtils.getTime());
            }
        }else {
            //新增第一个阅读人员
            List<String> stringList = new ArrayList<>();
            stringList.add(value);
            RedisUtils.setCacheList(READ_TRAIN + manualId, stringList);
            //key = read_train_time:manualId:userId
            RedisUtils.setCacheObject(READ_TRAIN_TIME + manualId + ":" + userId, DateUtils.getTime());
        }
        StaffTrainManual staffTrainManual = baseMapper.selectById(manualId);
        Long viewCount = staffTrainManual.getViewCount();
        staffTrainManual.setViewCount(viewCount+1);
        baseMapper.updateById(staffTrainManual);
        return MapstructUtils.convert(staffTrainManual, StaffTrainManualVo.class);
    }

    /**
     * 分页查询员工培训手册列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 员工培训手册分页列表
     */
    @Override
    public TableDataInfo<StaffTrainManualVo> queryPageList(StaffTrainManualBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<StaffTrainManual> lqw = buildQueryWrapper(bo);
        Page<StaffTrainManualVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的员工培训手册列表
     *
     * @param bo 查询条件
     * @return 员工培训手册列表
     */
    @Override
    public List<StaffTrainManualVo> queryList(StaffTrainManualBo bo) {
        LambdaQueryWrapper<StaffTrainManual> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<StaffTrainManual> buildQueryWrapper(StaffTrainManualBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<StaffTrainManual> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(StaffTrainManual::getManualId);
        lqw.eq(StringUtils.isNotBlank(bo.getManualTitle()), StaffTrainManual::getManualTitle, bo.getManualTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getManualType()), StaffTrainManual::getManualType, bo.getManualType());
        lqw.eq(StringUtils.isNotBlank(bo.getManualContent()), StaffTrainManual::getManualContent, bo.getManualContent());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), StaffTrainManual::getStatus, bo.getStatus());
        lqw.eq(bo.getPublishTime() != null, StaffTrainManual::getPublishTime, bo.getPublishTime());
        lqw.eq(StringUtils.isNotBlank(bo.getVideoUrl()), StaffTrainManual::getVideoUrl, bo.getVideoUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getCoverImage()), StaffTrainManual::getCoverImage, bo.getCoverImage());
        lqw.eq(StringUtils.isNotBlank(bo.getAuthor()), StaffTrainManual::getAuthor, bo.getAuthor());
        lqw.eq(StringUtils.isNotBlank(bo.getSource()), StaffTrainManual::getSource, bo.getSource());
        lqw.eq(bo.getViewCount() != null, StaffTrainManual::getViewCount, bo.getViewCount());
        lqw.eq(StringUtils.isNotBlank(bo.getProgress()), StaffTrainManual::getProgress, bo.getProgress());
        lqw.eq(StringUtils.isNotBlank(bo.getIsTop()), StaffTrainManual::getIsTop, bo.getIsTop());
        return lqw;
    }

    /**
     * 新增员工培训手册
     *
     * @param bo 员工培训手册
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(StaffTrainManualBo bo) {
        StaffTrainManual add = MapstructUtils.convert(bo, StaffTrainManual.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setManualId(add.getManualId());
        }
        return flag;
    }

    /**
     * 修改员工培训手册
     *
     * @param bo 员工培训手册
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(StaffTrainManualBo bo) {
        StaffTrainManual update = MapstructUtils.convert(bo, StaffTrainManual.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(StaffTrainManual entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除员工培训手册信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 获取已读人员名单
     */
    @Override
    public List<Map<String, String>> getRead(StaffTrainManual staffTrainManual) {
        //定义返回值
        List<Map<String, String>> resultList = new ArrayList<>();
        //String searchValue = staffTrainManual.getSearchValue();
        String author = staffTrainManual.getAuthor();
        Date searchTime = staffTrainManual.getCreateTime();
        Long manualId = staffTrainManual.getManualId();
        List<String> valueList = RedisUtils.getCacheList(READ_TRAIN + manualId);
        if (valueList != null && valueList.size() > 0) {
            //value = userId+":"+员工姓名
            for (String value : valueList) {
                String[] split = value.split(":");
                //key = read_train:manualId:userId
                String readTime = RedisUtils.getCacheObject(READ_TRAIN_TIME  + manualId + ":" + split[0]);
                Map<String, String> map = new HashMap<>(2);
                if (StringUtils.isBlank(author) && searchTime == null) {
                    map.put("name", split[1]);
                    //key = read_train:manualId:userId
                    map.put("time", readTime);
                    resultList.add(map);
                }
                //如果搜索姓名不为空
                else if (StringUtils.isNotBlank(author)) {
                    //如果搜索日期不为空
                    if (searchTime != null) {
                        // 创建日期格式化对象
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                        LocalDateTime dateTime = LocalDateTime.parse(readTime, formatter);
                        // 构造仅包含年月日的新时间字符串
                        LocalDate date = dateTime.toLocalDate();
                        String formattedDate = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        //split[1] = 员工姓名
                        if (split[1].contains(author) && sdf.format(searchTime).equals(formattedDate)) {
                            map.put("name", split[1]);
                            map.put("time", readTime);
                            resultList.add(map);
                        }
                    } else {
                        //搜索日期为空
                        if (split[1].contains(author)) {
                            map.put("name", split[1]);
                            map.put("time", readTime);
                            resultList.add(map);
                        }
                    }
                } else if (searchTime != null) {
                    // 创建日期格式化对象
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime dateTime = LocalDateTime.parse(readTime, formatter);
                    // 构造仅包含年月日的新时间字符串
                    LocalDate date = dateTime.toLocalDate();
                    String formattedDate = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    if (StringUtils.isNotBlank(author)) {
                        if (author.equals(split[1]) && sdf.format(searchTime).equals(formattedDate)) {
                            map.put("name", split[1]);
                            map.put("time", readTime);
                            resultList.add(map);
                        }
                    } else {
                        if (sdf.format(searchTime).equals(formattedDate)) {
                            map.put("name", split[1]);
                            map.put("time", readTime);
                            resultList.add(map);
                        }
                    }
                }else {
                    map.put("name", split[1]);
                    map.put("time", readTime);
                    resultList.add(map);
                }
            }
        }
        return resultList;
    }
}
