package com.srs.workstudy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.srs.common.core.domain.AjaxResult;
import com.srs.common.enums.QgzxApplyStatus;
import com.srs.workstudy.domain.QgzxMoney;
import com.srs.workstudy.domain.QgzxPost;
import com.srs.workstudy.domain.QgzxStuPost;
import com.srs.workstudy.domain.QgzxWorkLog;
import com.srs.workstudy.mapper.QgzxPostMapper;
import com.srs.workstudy.mapper.QgzxStuPostMapper;
import com.srs.workstudy.mapper.QgzxWorkLogMapper;
import com.srs.workstudy.service.IQgzxWorkLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.srs.common.utils.DateUtils.getNowDate;
import static com.srs.common.utils.SecurityUtils.getUsername;

/**
 * 勤工助学工作记录Service业务层处理
 *
 * @author srs
 * @date 2024-06-11
 */
@Service
public class QgzxWorkLogServiceImpl extends ServiceImpl<QgzxWorkLogMapper, QgzxWorkLog> implements IQgzxWorkLogService {
    @Autowired
    private QgzxWorkLogMapper qgzxWorkLogMapper;

    @Autowired
    private QgzxStuPostMapper _stuPostMapper;

    @Autowired
    private QgzxPostMapper _postMapper;

    @Autowired
    public PlatformTransactionManager transactionManager;

    @Override
    public AjaxResult cancelLog(Long id){
        try{
            QgzxWorkLog find = qgzxWorkLogMapper.selectById(id);
            if (find == null) {
                throw new Exception("该记录不存在");
            }
            if(!Objects.equals(find.applyStatus, "2")){
                throw new Exception("该记录未被审核通过，不能取消");
            }

            int res = qgzxWorkLogMapper.deleteById(id);
            if (res == 0) {
                throw new Exception("撤销失败");
            }

            return AjaxResult.success();
        }catch(Exception ex){
            return AjaxResult.error(ex.getMessage());
        }
    }



    @Override
    public List<HashMap<String,Object>> listWorkLogMonthTotal(QgzxWorkLog param){
        return qgzxWorkLogMapper.listWorkLogMonthTotal(param);
    }


    public AjaxResult manyAudit(List<QgzxWorkLog> param) {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        try {

            List<Long> ids = param.stream().map(x -> x.id).collect(Collectors.toList());
            QueryWrapper<QgzxWorkLog> query = new QueryWrapper<>();
            query.in("id", ids);
            List<QgzxWorkLog> list = qgzxWorkLogMapper.selectList(query);
            if (list.size() == 0) {
                throw new Exception("没有查询到记录");
            }
            param.forEach(x->{x.zdlsTime = getNowDate();});

            boolean res = this.updateBatchById(param);
            if (!res) {
                throw new Exception("更新审核状态失败，刷新试试");
            }

            transactionManager.commit(status);
            return AjaxResult.success();
        } catch (Exception ex) {
            transactionManager.rollback(status);
            return AjaxResult.error(ex.getMessage());
        }
    }

    @Override
    public AjaxResult computeTimeByStuNo(String stuNo) {
        try {
            QgzxWorkLog query = new QgzxWorkLog();
            query.stuNo = stuNo;
            QgzxWorkLog res = qgzxWorkLogMapper.computeMonthTime(query);
            return AjaxResult.success(res);
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }



    @Override
    public AjaxResult computeTime(QgzxMoney param){
        try {
            BigDecimal time = new BigDecimal("0");

            LocalDate now = param.applyTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            LocalDate firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
            LocalDate firstDayOfNextMonth = now.with(TemporalAdjusters.firstDayOfNextMonth());

            QueryWrapper<QgzxWorkLog> logQuery = new QueryWrapper<>();
            logQuery.eq("stu_post_id", param.stuPostId)
                    .ge("work_date", firstDayOfMonth)
                    .lt("work_date", firstDayOfNextMonth)
                    .eq("apply_status", "2");

            List<QgzxWorkLog> list = qgzxWorkLogMapper.selectList(logQuery);

            for (QgzxWorkLog log : list) {
                time = time.add(log.workTime);
            }

            if (time.compareTo(new BigDecimal("40")) > 0) {
                time = new BigDecimal("40");
            }

            Map<String, Object> res = new HashMap<>();
            res.put("time", time);
            return AjaxResult.success(res);
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }

    @Override
    public AjaxResult computeTimeById(Long id) {
        try {
            BigDecimal time = new BigDecimal("0");

            LocalDate now = getNowDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            LocalDate firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
            LocalDate firstDayOfNextMonth = now.with(TemporalAdjusters.firstDayOfNextMonth());

            QueryWrapper<QgzxWorkLog> logQuery = new QueryWrapper<>();
            logQuery.eq("stu_post_id", id)
                    .ge("work_date", firstDayOfMonth)
                    .lt("work_date", firstDayOfNextMonth)
                    .eq("apply_status", "2");

            List<QgzxWorkLog> list = qgzxWorkLogMapper.selectList(logQuery);

            for (QgzxWorkLog log : list) {
                time = time.add(log.workTime);
            }

            if (time.compareTo(new BigDecimal("40")) > 0) {
                time = new BigDecimal("40");
            }

            Map<String, Object> res = new HashMap<>();
            res.put("time", time);
            return AjaxResult.success(res);
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }

    @Override
    public AjaxResult doAudit(QgzxWorkLog param) {
        try {
            QgzxWorkLog workLog = qgzxWorkLogMapper.selectById(param.id);
            if (workLog == null) {
                throw new Exception("该申请记录已被删除，刷新试试");
            }

            QgzxStuPost stuPost = _stuPostMapper.selectById(workLog.stuPostId);

            QgzxPost post = _postMapper.selectById(stuPost.postId);
            if (post == null) {
                throw new Exception("该岗位已被删除");
            }

            if (!Objects.equals(stuPost.getZdlsNo(), getUsername())) {
                throw new Exception("您不是该岗位的指导老师");
            }

            if (Objects.equals(param.zdlsCmt, "通过")) {
                param.applyStatus = "2";

                LocalDate now = workLog.workDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

                LocalDate firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
                LocalDate firstDayOfNextMonth = now.with(TemporalAdjusters.firstDayOfNextMonth());

                List<String> applyStatusList = new ArrayList<>();
                applyStatusList.add("1");
                applyStatusList.add("2");

                QueryWrapper<QgzxWorkLog> queryWrapper = new QueryWrapper<>();
                queryWrapper
                        .ne("id", param.id)
                        .eq("stu_post_id", workLog.stuPostId)
                        .ge("work_date", firstDayOfMonth)
                        .lt("work_date", firstDayOfNextMonth)
                        .in("apply_status", applyStatusList);

                List<QgzxWorkLog> list = qgzxWorkLogMapper.selectList(queryWrapper);

                BigDecimal monthTotal = new BigDecimal("0");

                for (QgzxWorkLog log : list) {
                    monthTotal = monthTotal.add(log.workTime);
                }
                monthTotal = monthTotal.add(param.workTime);

                BigDecimal result = monthTotal.subtract(new BigDecimal("40"));
                if (result.compareTo(new BigDecimal("0")) > 0) {
                    throw new Exception("当前提交月份的工时超过40小时，建议改为:" + (param.workTime.subtract(result)));
                }

            } else {
                param.applyStatus = "10";
            }

            param.zdlsTime = getNowDate();
            int res = qgzxWorkLogMapper.updateById(param);
            if (res == 0) {
                throw new Exception("修改状态失败");
            }

            return AjaxResult.success();
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }

    //判断在不在五天内
    public static boolean isTodayOrYesterday(Date date) {
        Date now = new Date();

        Date specifiedDate = date;

        long diffInMillies = Math.abs(now.getTime() - specifiedDate.getTime());
        long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
        // 判断时间差是否大于5天
        if (diff > 5) {
            return false;
        } else {
            return true;
        }
    }

    public List<QgzxWorkLog> listView(QgzxWorkLog param) {
        return qgzxWorkLogMapper.listView(param);
    }

    @Override
    public AjaxResult cancelApply(Long id) {
        try {
            QgzxWorkLog find = qgzxWorkLogMapper.selectById(id);
            if (find == null) {
                throw new Exception("申请记录不存在");
            }

            if (!Objects.equals(find.applyStatus, "0") && !Objects.equals(find.applyStatus, "1")) {
                throw new Exception("该记录已被审核,不能取消申请");
            }

            QgzxStuPost stuPost = _stuPostMapper.selectById(find.stuPostId);

            if (!Objects.equals(stuPost.stuNo, getUsername())) {
                throw new Exception("不是本人");
            }

            int res = qgzxWorkLogMapper.deleteQgzxWorkLogById(id);
            if (res == 0) {
                throw new Exception("取消失败");
            }

            return AjaxResult.success();
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }


    public AjaxResult doSave(QgzxWorkLog param) {
        try {
            QgzxStuPost stuPost = _stuPostMapper.selectById(param.stuPostId);
            if (stuPost == null) {
                throw new Exception("学生岗位不存在");
            }

            if (!Objects.equals(stuPost.stuNo, getUsername())) {
                throw new Exception("不是您的岗位");
            }

//            if (!isTodayOrYesterday(param.workDate)) {
//                throw new Exception("错误的日期");
//            }

            QueryWrapper<QgzxWorkLog> query = new QueryWrapper<>();
            query.eq("stu_post_id", stuPost.id)
                    .eq("work_date", param.workDate)
                    .ne("apply_status", QgzxApplyStatus.REJECTED.getCode());
            List<QgzxWorkLog> list = qgzxWorkLogMapper.selectList(query);
            if (list.size() != 0) {
                throw new Exception("工作日期已填报");
            }

            param.applyStatus = QgzxApplyStatus.SAVED.getCode();
            param.applyTime = getNowDate();

            boolean res = this.saveOrUpdate(param);

            if (!res) {
                throw new Exception("保存失败");
            }

            return AjaxResult.success();
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }

    public AjaxResult doApply(QgzxWorkLog param) {
        try {
            QgzxStuPost stuPost = _stuPostMapper.selectById(param.stuPostId);
            if (stuPost == null) {
                throw new Exception("学生岗位不存在");
            }

            if (!Objects.equals(stuPost.stuNo, getUsername())) {
                throw new Exception("不是您的岗位");
            }


//            if (!isTodayOrYesterday(param.workDate)) {
//                throw new Exception("错误的日期");
//            }

            QueryWrapper<QgzxWorkLog> query2 = new QueryWrapper<>();
            query2.eq("stu_post_id", stuPost.id)
                    .eq("work_date", param.workDate)
                    .ne("apply_status", QgzxApplyStatus.REJECTED.getCode());
            List<QgzxWorkLog> list2 = qgzxWorkLogMapper.selectList(query2);
            if (list2.size() != 0) {
                throw new Exception("工作日期已填报");
            }


            LocalDate now = param.workDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

            LocalDate firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
            LocalDate firstDayOfNextMonth = now.with(TemporalAdjusters.firstDayOfNextMonth());

            List<String> applyStatusList = new ArrayList<>();
//            applyStatusList.add("1");
//            applyStatusList.add("2");

            applyStatusList.add(QgzxApplyStatus.SUBMITTED.getCode());
            applyStatusList.add(QgzxApplyStatus.INSTRUCTOR_APPROVED.getCode());

            QueryWrapper<QgzxWorkLog> queryWrapper = new QueryWrapper<>();
            queryWrapper
                    .eq("stu_post_id", param.stuPostId)
                    .ge("work_date", firstDayOfMonth)
                    .lt("work_date", firstDayOfNextMonth)
                    .in("apply_status", applyStatusList);

            List<QgzxWorkLog> list = qgzxWorkLogMapper.selectList(queryWrapper);

            BigDecimal monthTotal = new BigDecimal("0");

            for (QgzxWorkLog log : list) {
                monthTotal = monthTotal.add(log.workTime);
            }
            monthTotal = monthTotal.add(param.workTime);

            BigDecimal result = monthTotal.subtract(new BigDecimal("40"));
            if (result.compareTo(new BigDecimal("0")) > 0) {
                throw new Exception("当前提交月份的工时超过40小时，建议改为:" + (param.workTime.subtract(result)));
            }

            LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            LocalDate endOfWeek = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

            QueryWrapper<QgzxWorkLog> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1
                    .eq("stu_post_id", param.stuPostId)
                    .ge("work_date", startOfWeek)
                    .lt("work_date", endOfWeek.plusDays(1))
                    .in("apply_status", applyStatusList);

            List<QgzxWorkLog> list1 = qgzxWorkLogMapper.selectList(queryWrapper1);

            BigDecimal weekTotal = new BigDecimal("0");

            for (QgzxWorkLog log : list1) {
                weekTotal = weekTotal.add(log.workTime);
            }
            weekTotal = weekTotal.add(param.workTime);

//            BigDecimal result1 = weekTotal.subtract(new BigDecimal("8"));
//            if (result1.compareTo(new BigDecimal("0")) > 0) {
//                throw new Exception("当前提交本周的工时超过8小时，建议改为:" + (param.workTime.subtract(result1)));
//            }

            param.applyStatus = "1";
            param.applyTime = getNowDate();

            boolean res = this.saveOrUpdate(param);

            if (!res) {
                throw new Exception("申请失败");
            }
            return AjaxResult.success();
        } catch (Exception ex) {
            return AjaxResult.error(ex.getMessage());
        }
    }


    /**
     * 查询勤工助学工作记录
     *
     * @param id 勤工助学工作记录主键
     * @return 勤工助学工作记录
     */
    @Override
    public QgzxWorkLog selectQgzxWorkLogById(Long id) {
        return qgzxWorkLogMapper.selectQgzxWorkLogById(id);
    }

    /**
     * 查询勤工助学工作记录列表
     *
     * @param qgzxWorkLog 勤工助学工作记录
     * @return 勤工助学工作记录
     */
    @Override
    public List<QgzxWorkLog> selectQgzxWorkLogList(QgzxWorkLog qgzxWorkLog) {
        return qgzxWorkLogMapper.selectQgzxWorkLogList(qgzxWorkLog);
    }

    /**
     * 新增勤工助学工作记录
     *
     * @param qgzxWorkLog 勤工助学工作记录
     * @return 结果
     */
    @Override
    public int insertQgzxWorkLog(QgzxWorkLog qgzxWorkLog) {
        return qgzxWorkLogMapper.insertQgzxWorkLog(qgzxWorkLog);
    }

    /**
     * 修改勤工助学工作记录
     *
     * @param qgzxWorkLog 勤工助学工作记录
     * @return 结果
     */
    @Override
    public int updateQgzxWorkLog(QgzxWorkLog qgzxWorkLog) {
        return qgzxWorkLogMapper.updateQgzxWorkLog(qgzxWorkLog);
    }

    /**
     * 批量删除勤工助学工作记录
     *
     * @param ids 需要删除的勤工助学工作记录主键
     * @return 结果
     */
    @Override
    public int deleteQgzxWorkLogByIds(Long[] ids) {
        return qgzxWorkLogMapper.deleteQgzxWorkLogByIds(ids);
    }

    /**
     * 删除勤工助学工作记录信息
     *
     * @param id 勤工助学工作记录主键
     * @return 结果
     */
    @Override
    public int deleteQgzxWorkLogById(Long id) {
        return qgzxWorkLogMapper.deleteQgzxWorkLogById(id);
    }
}
