package com.staffing.custom.service.impl;

import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.staffing.common.utils.DateUtils;
import com.staffing.common.utils.MinioUtil;
import com.staffing.common.utils.QRCodeGenerator;
import com.staffing.custom.domain.StEmployee;
import com.staffing.custom.domain.StEmployeeFundRecord;
import com.staffing.custom.domain.StTaskSign;
import com.staffing.custom.mapper.StEmployeeFundRecordMapper;
import com.staffing.custom.mapper.StTaskSignMapper;
import io.minio.ObjectWriteResponse;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.staffing.custom.mapper.StTaskMapper;
import com.staffing.custom.domain.StTask;
import com.staffing.custom.service.IStTaskService;

import static com.staffing.common.utils.PageUtils.startPage;

/**
 * 任务Service业务层处理
 * 
 * @author staffing
 * @date 2024-08-27
 */
@Service
public class StTaskServiceImpl implements IStTaskService 
{
    @Autowired
    private StTaskMapper stTaskMapper;

    @Autowired
    private StTaskSignMapper stTaskSignMapper;
    @Autowired
    private StEmployeeFundRecordMapper stEmployeeFundRecordMapper;

    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private RedissonClient redissonClient;

    protected final Logger logger = LoggerFactory.getLogger(StTaskServiceImpl.class);

    @Override
    public StTask selectStTaskById(Long id){
        return selectStTaskById(id, false);
    }
    /**
     * 查询任务
     * 
     * @param id 任务主键
     * @return 任务
     */
    @Override
    public StTask selectStTaskById(Long id, boolean filterSign)
    {
        StTask stTask = stTaskMapper.selectStTaskById(id);

        StEmployeeFundRecord employeeFundRecord = new StEmployeeFundRecord();
        employeeFundRecord.setTaskId(id);
        List<StEmployeeFundRecord> fundRecords = stEmployeeFundRecordMapper.selectStEmployeeFundRecordList(employeeFundRecord);
        Map<Long, StEmployeeFundRecord> fundMap = new HashMap<>();
        for (StEmployeeFundRecord fundRecord : fundRecords) {
            fundMap.put(fundRecord.getEmployeeId(), fundRecord);
        }
        StTaskSign param = new StTaskSign();
        param.setTaskId(stTask.getId());
        List<StTaskSign> stTaskSignsTemp = stTaskSignMapper.selectStTaskSignList(param);
        List<StTaskSign> stTaskSigns;
        if (filterSign){
            stTaskSigns = new ArrayList<>();
            for (StTaskSign taskSign : stTaskSignsTemp) {
                if (taskSign.getStatus() == 1){
                    stTaskSigns.add(taskSign);
                }
            }
        }else{
            stTaskSigns = stTaskSignsTemp;
        }

        stTask.setListSign(stTaskSigns);

        int signNum = 0;
        int noSignNum = 0;
        for (StTaskSign stTaskSign1 : stTaskSigns) {
            if (stTaskSign1.getStatus() == 1){
                signNum ++;
            }else if (stTaskSign1.getStatus() == 0){
                noSignNum++;
            }
            stTaskSign1.setTaskName(stTask.getTaskName());
            stTaskSign1.setDayPrice(stTask.getDayPrice());

            stTaskSign1.setStEmployeeFundRecord(fundMap.get(stTaskSign1.getEmployeeId()));
        }
        stTask.setSignNum(signNum);
        stTask.setNoSignNum(noSignNum);
        stTask.setBaomingNum(stTask.getListSign().size());

        return stTask;
    }

    /**
     * 查询任务列表
     * 
     * @param stTask 任务
     * @return 任务
     */
    @Override
    public List<StTask> selectStTaskList(StTask stTask, long uid)
    {
        List<StTask> stTasks = stTaskMapper.selectStTaskList(stTask);
        if (stTasks.isEmpty())
            return stTasks;
        for (StTask task : stTasks) {
            if (task.getCodePic() == null){
                generatePrCode(task);
            }
        }

        return supplement(stTasks, uid);
    }


    /**
     * 填充签到信息
     * @param stTasks
     * @return
     */
    private List<StTask> supplement(List<StTask> stTasks, long uid) {
        List<Long> taskIds = stTasks.stream().map(stTask1 -> stTask1.getId()).collect(Collectors.toList());
        if (taskIds.isEmpty()){
            return stTasks;
        }

        List<StEmployeeFundRecord> fundRecords = stEmployeeFundRecordMapper.selectStEmployeeFundRecordByTaskIds(taskIds);
        Map<Long, Map<Long, StEmployeeFundRecord>> taskFundMap = new HashMap<>();
        for (StEmployeeFundRecord fundRecord : fundRecords) {
            Map<Long, StEmployeeFundRecord> fundRecordMap = taskFundMap.computeIfAbsent(fundRecord.getTaskId(), v -> new HashMap<>());
            fundRecordMap.put(fundRecord.getEmployeeId(), fundRecord);
        }

        List<StTaskSign> stTaskSigns = stTaskSignMapper.selectStTaskSignByTaskIds(taskIds);
        Map<Long, List<StTaskSign>> taskSignMap = new HashMap<>();
        for (StTaskSign stTaskSign : stTaskSigns) {
            List<StTaskSign> stTaskSignsList = taskSignMap.computeIfAbsent(stTaskSign.getTaskId(), v -> new ArrayList<>());
            stTaskSignsList.add(stTaskSign);
        }

        for (StTask task : stTasks) {
            task.setListSign(taskSignMap.get(task.getId()));
            Map<Long, StEmployeeFundRecord> employeeFundRecordMap = taskFundMap.get(task.getId());


            if (task.getListSign() == null){
                task.setSignNum(0);
                task.setBaomingNum(0);
                task.setYfNum(0);
                task.setSfNum(0);
                task.setDfNum(0);
                task.setYfPrice(0+"");
                task.setSfPrice(0+"");
                task.setDfPrice(0+"");
                continue;
            }
            int signNum = 0;
            int noSignNum = 0;
            int yfNum = 0;//应发
            int sfNum = 0;//实发
            int dfNum = 0;//待发
            BigDecimal yfPrice = new BigDecimal(0);
            BigDecimal sfPrice = new BigDecimal(0);
            BigDecimal dfPrice = new BigDecimal(0);


            for (StTaskSign stTaskSign : task.getListSign()) {


                if (stTaskSign.getStatus() == 0){
                    noSignNum++;
                }
                if (stTaskSign.getStatus() == 1){
                    signNum ++;
                    yfNum++;

                    if (employeeFundRecordMap != null){
                        StEmployeeFundRecord fundRecord = employeeFundRecordMap.get(stTaskSign.getEmployeeId());
                        if (fundRecord != null){
                            stTaskSign.setStEmployeeFundRecord(fundRecord);
                            if (fundRecord.getPayStatus() == 1){
                                sfNum++;
                                sfPrice = sfPrice.add(new BigDecimal(fundRecord.getRealPrice()));
                            }
                            yfPrice = yfPrice.add(new BigDecimal(fundRecord.getRealPrice()));
                        }
                    }
                }

                stTaskSign.setTaskName(task.getTaskName());
                stTaskSign.setDayPrice(task.getDayPrice());


                if (stTaskSign.getEmployeeId() == uid){
                    task.setSelfSign(stTaskSign);
                }
            }
            dfNum = yfNum - sfNum;
            dfPrice = yfPrice.subtract(sfPrice);

            task.setYfNum(yfNum);
            task.setSfNum(sfNum);
            task.setDfNum(dfNum);
            task.setYfPrice(yfPrice.toString());
            task.setSfPrice(sfPrice.toString());
            task.setDfPrice(dfPrice.toString());
            task.setSignNum(signNum);
            task.setNoSignNum(noSignNum);
            task.setBaomingNum(task.getListSign().size());

        }
        return stTasks;
    }

    public List<StTask> selectStTaskListByUserId(StTask stTask, Long userId, boolean sign){
        StTaskSign stTaskSign = new StTaskSign();
        stTaskSign.setEmployeeId(userId);
        if (sign){
            stTaskSign.setStatus(1);
        }

        List<StTaskSign> stTaskSigns = stTaskSignMapper.selectStTaskSignList(stTaskSign);
        if (stTaskSigns.isEmpty()){
            return new ArrayList<>();
        }

        Map<Long, StTaskSign> taskSignMap = new HashMap<>();
        for (StTaskSign taskSign : stTaskSigns) {
            taskSignMap.put(taskSign.getTaskId(), taskSign);
        }
        stTask.setTaskIds(taskSignMap.keySet());
        startPage();
        List<StTask> stTasks = stTaskMapper.selectStTaskList(stTask);

        for (StTask task : stTasks) {
            task.setSelfSign(taskSignMap.get(task.getId()));
        }

        return supplement(stTasks, userId);
    }

    /**
     * 新增任务
     * 
     * @param stTask 任务
     * @return 结果
     */
    @Override
    public int insertStTask(StTask stTask)
    {
        int i = stTaskMapper.insertStTask(stTask);
        List<StTaskSign> listSign = stTask.getListSign();
        for (StTaskSign stTaskSign : listSign) {
            stTaskSign.setTaskId(stTask.getId());
            stTaskSign.setStatus(-1);
            stTaskSign.setDayPrice(stTask.getDayPrice());
            stTaskSign.setTaskName(stTask.getTaskName());
            stTaskSignMapper.insertStTaskSign(stTaskSign);
        }
        return i;
    }

    @Override
    public int updateStTask(StTask stTask){
        return updateStTask(stTask, true);
    }
    /**
     * 修改任务
     * 
     * @param stTask 任务
     * @return 结果
     */
    @Override
    public int updateStTask(StTask stTask, boolean syncRelationsTabel)
    {
        RLock lock = redissonClient.getLock(stTask.getId() + "");
        try {
            lock.lock();

            if (syncRelationsTabel){
                //签到表
                StTaskSign stTaskSignUpdate = new StTaskSign();
                stTaskSignUpdate.setTaskName(stTask.getTaskName());
                stTaskSignUpdate.setDayPrice(stTask.getDayPrice());
                stTaskSignUpdate.setTaskId(stTask.getId());
                stTaskSignMapper.updateStTaskSignByTaskId(stTaskSignUpdate);

                //流水表
                StEmployeeFundRecord stEmployeeFundRecord = new StEmployeeFundRecord();
                stEmployeeFundRecord.setTaskName(stTask.getTaskName());
                stEmployeeFundRecord.setDayPrice(stTask.getDayPrice());
                stEmployeeFundRecord.setTaskId(stTask.getId());
                stEmployeeFundRecord.setRealPrice(stTask.getDayPrice());
                stEmployeeFundRecord.setTaskDate(stTask.getTaskDate());
                stEmployeeFundRecordMapper.updateStEmployeeFundRecordByTask(stEmployeeFundRecord);
            }

            stTask.setUpdateTime(DateUtils.getNowDate());

            StTaskSign param = new StTaskSign();
            param.setTaskId(stTask.getId());
            List<StTaskSign> stTaskSigns = stTaskSignMapper.selectStTaskSignList(param);
            Map<Long, StTaskSign> stTaskSignMap = new HashMap<>();
            for (StTaskSign stTaskSign : stTaskSigns) {
                stTaskSignMap.put(stTaskSign.getEmployeeId(), stTaskSign);
            }

            List<StTaskSign> listSign = stTask.getListSign();
            if (listSign != null) {
                for (StTaskSign stTaskSign : listSign) {
                    if (!stTaskSignMap.containsKey(stTaskSign.getEmployeeId())) {
                        stTaskSign.setTaskId(stTask.getId());
                        stTaskSign.setStatus(-1);
                        stTaskSign.setDayPrice(stTask.getDayPrice());
                        stTaskSign.setTaskName(stTask.getTaskName());
                        stTaskSignMapper.insertStTaskSign(stTaskSign);
                    }
                    stTaskSignMap.remove(stTaskSign.getEmployeeId());
                }
                for (Map.Entry<Long, StTaskSign> longStTaskSignEntry : stTaskSignMap.entrySet()) {
                    stTaskSignMapper.deleteStTaskSignById(longStTaskSignEntry.getValue().getId());
                }
            }
            return stTaskMapper.updateStTask(stTask);
        }finally {
            // 锁被持有
            if (lock != null && lock.isLocked()) {
                if (lock.isHeldByCurrentThread()) {
                    //  解锁
                    lock.unlock();
                }
            }
        }
    }

    public int generatePrCode(StTask stTask){
        String url = "http://www.tulkj.cn:81/index.html?id=" + stTask.getId();
        InputStream inputStream = QRCodeGenerator.generateQRCodeImage(url, 500, 500);
        String fileName = System.currentTimeMillis() + stTask.getId() + ".png";
        try {
            ObjectWriteResponse objectWriteResponse = minioUtil.putObject("yonggong"
                    , fileName, inputStream, inputStream.available(), "image/png");
        } catch (Exception e) {
            logger.error("minioUtil.putObject error", e);
        }

        stTask.setCodePic(fileName);

        return updateStTask(stTask);
    }

    /**
     * 批量删除任务
     * 
     * @param ids 需要删除的任务主键
     * @return 结果
     */
    @Override
    public int deleteStTaskByIds(Long[] ids)
    {
        return stTaskMapper.deleteStTaskByIds(ids);
    }

    /**
     * 删除任务信息
     * 
     * @param id 任务主键
     * @return 结果
     */
    @Override
    public int deleteStTaskById(Long id)
    {
        return stTaskMapper.deleteStTaskById(id);
    }


    public void updateTaskUserInfo(StEmployee stEmployee) {
        //将相关报名信息修改
        StTaskSign stTaskSign = new StTaskSign();
        stTaskSign.setEmployeeId(stEmployee.getId());
        stTaskSign.setEmployeeName(stEmployee.getRealName());
        stTaskSign.setIdCard(stEmployee.getIdCard());
        stTaskSignMapper.updateStTaskSignByEmId(stTaskSign);


        StEmployeeFundRecord stEmployeeFundRecord = new StEmployeeFundRecord();
        stEmployeeFundRecord.setEmployeeId(stEmployee.getId());
        stEmployeeFundRecord.setEmployeeName(stEmployee.getRealName());
        stEmployeeFundRecord.setIdCard(stEmployee.getIdCard());
        stEmployeeFundRecordMapper.updateStEmployeeFundRecordByEmId(stEmployeeFundRecord);
    }
}
