package cn.com.ty.lift.enterprise.oa.service;

import cn.com.ty.lift.common.utils.ValuePool;
import cn.com.ty.lift.common.verify.Validate;
import cn.com.ty.lift.enterprise.oa.dto.AttendanceRequest;
import cn.com.ty.lift.enterprise.oa.dto.AttendanceResponse;
import cn.com.ty.lift.enterprise.oa.entity.Attendance;
import cn.com.ty.lift.enterprise.oa.entity.MaintenanceCompany;
import cn.com.ty.lift.enterprise.oa.mapper.AttendanceMapper;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.FileNotFoundException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

/**
 * <p>
 * 打卡签到记录 服务类
 * </p>
 *
 * @author wcz
 * @since 2019-12-12
 */
@Service
@Slf4j
public class AttendanceService extends ServiceImpl<AttendanceMapper, Attendance> {
    @Resource
    MaintenanceCompanyService maintenanceCompanyService;

    /**
     * 根据条件分页查找签到记录
     *
     * @param request AttendanceRequest
     * @return IPage<AttendanceResponse>
     */
    public IPage<AttendanceResponse> pageByCondition(AttendanceRequest request) {
        return baseMapper.pageByCondition(request.getPage(), request);
    }

    /**
     * 根据用户分页查找记录
     *
     * @param request AttendanceRequest
     * @return IPage<AttendanceResponse>
     */
    public IPage<AttendanceResponse> pageByUser(AttendanceRequest request) {
        return baseMapper.pageByUser(request.getPage(), request);
    }

    public List<AttendanceResponse> listByIdList(AttendanceRequest request) {
        return baseMapper.listByIdList(request);
    }

    /**
     * 根据用户和打卡类型统计打卡记录条数
     *
     * @param mtCompanyId 维保公司id
     * @param userId      用户id
     * @param type        打卡类型
     * @return int
     */
    public Attendance sameByUserAndType(Long mtCompanyId, Long userId, Integer type) {
        LambdaQueryWrapper<Attendance> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Attendance::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(Attendance::getUserId, userId);
        lambdaQueryWrapper.eq(Attendance::getType, type);
        //查询当天的打卡记录
        LocalDateTime today = LocalDateTime.now();
        lambdaQueryWrapper.between(Attendance::getCreateDate, today.with(LocalTime.MIN), today.with(LocalTime.MAX));
        lambdaQueryWrapper.last("LIMIT 1");
        return getOne(lambdaQueryWrapper);
    }

    /**
     * 根据id查询，带关联信息
     *
     * @param request
     * @return
     */
    public AttendanceResponse infoById(AttendanceRequest request) {
        return baseMapper.infoById(request);
    }

    public long countByMtCompany(Long mtCompanyId) {
        LambdaQueryWrapper<Attendance> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Attendance::getMtCompanyId, mtCompanyId);
        return count(lambdaQueryWrapper);
    }

    public void export(AttendanceRequest attendanceRequest, HttpServletResponse response) {
        if (attendanceRequest.getUserIds()==null||attendanceRequest.getUserIds().isEmpty()) {
            attendanceRequest.setUserIds(this.baseMapper.selectCompanyUserIdsByMtCompanyId(attendanceRequest.getMtCompanyId()));
        }
        attendanceRequest.setUserId(null);
        List<AttendanceResponse> attendanceResponses = this.listByIdList(attendanceRequest);
        Validate.notNull(attendanceResponses, ValuePool.ATTEND_MISSING);
        ExcelWriter writer = ExcelUtil.getWriter(true);
        HashMap<String, String> attendances = new HashMap<>();
        Set<String> userIds = new HashSet<>();
        for (AttendanceResponse attendance : attendanceResponses) {
            int type = ValuePool.nullable(attendance.getType(), 0);
            Long userId = attendance.getUserId();
            int dayOfMonth = attendance.getCreateDate().getDayOfMonth();
            String attendanceTime = String.format("%tT", attendance.getCreateDate()) + " " + attendance.getStatusDesc();
            switch (type) {
                case 1:
                case 11:
                    attendances.put(userId + "topTime" + dayOfMonth, attendanceTime);
                    break;
                case 12:
                    attendances.put(userId + "downTime" + dayOfMonth, attendanceTime);
                    break;
                case 21:
                    attendances.put(userId + "topTimePm" + dayOfMonth, attendanceTime);
                    break;
                case 2:
                case 22:
                    attendances.put(userId + "downTimePm" + dayOfMonth, attendanceTime);
                    break;
                case 31:
                    attendances.put(userId + "topTimeOt" + dayOfMonth, attendanceTime);
                    break;
                case 32:
                    attendances.put(userId + "downTimeOt" + dayOfMonth, attendanceTime);
                    break;
            }
            attendances.put(userId.toString(), attendance.getUsername() + "   " + attendance.getUserMobile());
            userIds.add(userId.toString());
        }
        MaintenanceCompany attendanceTime = maintenanceCompanyService.getById(attendanceRequest.getMtCompanyId());
        String[] split = attendanceRequest.getAttendanceYearMonth().trim().split("-");
        log.info("用户数量" + userIds.size());
        try {
            writeExcel(Integer.parseInt(split[0]), Integer.parseInt(split[1]), writer, attendances, userIds, attendanceTime);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + IdWorker.getIdStr() + ".xlsx");
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } catch (Exception e) {
            log.error("导出打卡记录异常", e);
            throw Validate.validateException("导出打卡记录异常");
        }
    }

    private void writeExcel(int year, int month, ExcelWriter writer, Map<String, String> attendances, Set<String> userIds, MaintenanceCompany attendanceTime) throws FileNotFoundException {
        int lengthOfMonth = LocalDate.of(year, month, 1).lengthOfMonth();
        writer.merge(0, 0, 0, lengthOfMonth, year + "年" + month + "月签到记录表", false);
        writer.setColumnWidth(0, 20);
        Iterator<String> iterator = userIds.iterator();
        int i = 0;
        while (iterator.hasNext()) {
            String userId = iterator.next();
            int col = i * 9;
            int j = 1;
            for (; j <= lengthOfMonth; j++) {
                writer.setColumnWidth(j, 15);
                writer.writeCellValue(j, col + 1, j);
                //写入每个用户每天的打卡信息
                writer.writeCellValue(j, col + 3, Optional.ofNullable(attendances.get(userId + "topTime" + j)).orElse(""));
                writer.writeCellValue(j, col + 4, Optional.ofNullable(attendances.get(userId + "downTime" + j)).orElse(""));
                writer.writeCellValue(j, col + 5, Optional.ofNullable(attendances.get(userId + "topTimePm" + j)).orElse(""));
                writer.writeCellValue(j, col + 6, Optional.ofNullable(attendances.get(userId + "downTimePm" + j)).orElse(""));
                writer.writeCellValue(j, col + 7, Optional.ofNullable(attendances.get(userId + "topTimeOt" + j)).orElse(""));
                writer.writeCellValue(j, col + 8, Optional.ofNullable(attendances.get(userId + "downTimeOt" + j)).orElse(""));
            }
            //写入公司的打卡时间
            writer.merge(col + 1, col + 2, 0, 0, "应打卡时间", false);
            writer.writeCellValue(0, col + 3, "上午上班时间" + (attendanceTime.getTopTime() != null ? attendanceTime.getTopTime().toString() : "未设置"));
            writer.writeCellValue(0, col + 4, "上午下班时间" + (attendanceTime.getDownTime() != null ? attendanceTime.getDownTime().toString() : "未设置"));
            writer.writeCellValue(0, col + 5, "下午上班时间" + (attendanceTime.getTopTimePm() != null ? attendanceTime.getTopTimePm().toString() : "未设置"));
            writer.writeCellValue(0, col + 6, "下午下班时间" + (attendanceTime.getDownTimePm() != null ? attendanceTime.getDownTimePm().toString() : "未设置"));
            writer.writeCellValue(0, col + 7, "加班上班时间" + (attendanceTime.getTopTimeOt() != null ? attendanceTime.getTopTimeOt().toString() : "未设置"));
            writer.writeCellValue(0, col + 8, "加班下班时间" + (attendanceTime.getDownTimeOt() != null ? attendanceTime.getDownTimeOt().toString() : "未设置"));
            writer.merge(col + 2, col + 2, 1, j - 1, attendances.get(userId), false);
            i++;
        }
    }
}