package com.ruoyi.zhushi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.zhushi.entity.AppDTO;
import com.ruoyi.zhushi.entity.DkCheckInRecord;
import com.ruoyi.zhushi.mapper.DkAttendanceGroupMapper;
import com.ruoyi.zhushi.mapper.DkRecordMapper;
import com.ruoyi.zhushi.service.DkAppService;
import com.ruoyi.zhushi.util.GeoDistanceUtil;
import com.ruoyi.zhushi.util.TimeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;

@Service
public class DkAppServiceImpl implements DkAppService {

    @Autowired
    private DkAttendanceGroupMapper dkAttendanceGroupMapper;

    @Autowired
    private DkRecordMapper dkRecordMapper;

    @Override
    public String checkIn(AppDTO appDTO) {
        AppDTO appDTO1 = dkAttendanceGroupMapper.queryAttendanceGroupBYUserId(appDTO.getUserId());

        // 判断是否已经打卡，如果已经打卡，则不允许再次打卡
        LambdaQueryWrapper<DkCheckInRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DkCheckInRecord::getSysUserId, appDTO.getUserId());
        queryWrapper.apply("DATE(check_in_time) = DATE(NOW())");
        List<DkCheckInRecord> dkCheckInRecords = dkRecordMapper.selectList(queryWrapper);
        if (dkCheckInRecords.size() > 0){
            return "已经打卡,不允许重复打卡！";
        }
        // 打卡开始时间
        String workStartTime = appDTO1.getWorkStartTime();
        if(workStartTime == null){
            return "系统设置错误";
        }

        // 根据经纬度计算两点之间的距离
//        double distanceKm = GeoDistanceUtil.getDistanceKm(appDTO.getLat(), appDTO.getLng(), appDTO1.getLat(), appDTO1.getLng());
//        if (distanceKm > appDTO.getRadius()) {
//            return "超出打卡范围";
//        }

        // 解析给定的时分秒（格式：HH:mm:ss 或 HH:mm）
        // true的时候表示当前时间在给定时间以前，属于正常打卡；false表示当前时间在给定时间以后，属于迟到打卡
        boolean result = canSignIn(workStartTime);
        // 初始化打卡记录对象
        DkCheckInRecord dkCheckInRecord = new DkCheckInRecord();

        if(!result){
            // 允许迟到打卡
            if(appDTO1.getAllowLate()){
                // 根据允许的范围进行是否可以打卡判断
                boolean b = allowCheckIn(workStartTime, appDTO1.getLateRange());
                // true 表示在可以迟到的时间内，进行正常打卡
                if(!b){
                    dkCheckInRecord.setSysUserId(appDTO.getUserId());
                    dkCheckInRecord.setSysUserName(appDTO.getUserName());
                    dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
                    dkCheckInRecord.setClockIn(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
                    dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
                    if (null != appDTO.getCheckInStatus()){
                        dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                        dkCheckInRecord.setClockInStatus(appDTO.getCheckInStatus());
                    } else {
                        dkCheckInRecord.setCheckInStatus("3");
                        dkCheckInRecord.setClockInStatus("3");
                    }
                    dkCheckInRecord.setClockInStatus(appDTO.getCheckInStatus());
//                    dkCheckInRecord.setCheckInStatus("3");
                    dkCheckInRecord.setMonth(appDTO.getMonth());
                    dkCheckInRecord.setWeek(appDTO.getWeek());
                    dkCheckInRecord.setDay(appDTO.getDay());
                    dkCheckInRecord.setDescription(appDTO.getDescription());
                    dkRecordMapper.insert(dkCheckInRecord);
                    return "迟到打卡";
                }
                dkCheckInRecord.setSysUserId(appDTO.getUserId());
                dkCheckInRecord.setSysUserName(appDTO.getUserName());
                dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
                dkCheckInRecord.setClockIn(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
                dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
                if (null != appDTO.getCheckInStatus()){
                    dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                    dkCheckInRecord.setClockInStatus(appDTO.getCheckInStatus());
                } else {
                    dkCheckInRecord.setCheckInStatus("1");
                    dkCheckInRecord.setClockInStatus("1");
                }
//                dkCheckInRecord.setCheckInStatus("1");
                dkCheckInRecord.setMonth(appDTO.getMonth());
                dkCheckInRecord.setWeek(appDTO.getWeek());
                dkCheckInRecord.setDay(appDTO.getDay());
                dkCheckInRecord.setDescription(appDTO.getDescription());
                dkRecordMapper.insert(dkCheckInRecord);
                return "打卡成功";
            }else{
                dkCheckInRecord.setSysUserId(appDTO.getUserId());
                dkCheckInRecord.setSysUserName(appDTO.getUserName());
                dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
                dkCheckInRecord.setClockIn(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
                dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
                if (null != appDTO.getCheckInStatus()){
                    dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                    dkCheckInRecord.setClockInStatus(appDTO.getCheckInStatus());
                } else {
                    dkCheckInRecord.setCheckInStatus("3");
                    dkCheckInRecord.setClockInStatus("3");
                }
                dkCheckInRecord.setMonth(appDTO.getMonth());
                dkCheckInRecord.setWeek(appDTO.getWeek());
                dkCheckInRecord.setDay(appDTO.getDay());
                dkCheckInRecord.setDescription(appDTO.getDescription());
                dkRecordMapper.insert(dkCheckInRecord);
                return "迟到打卡";
            }
        }


        dkCheckInRecord.setSysUserId(appDTO.getUserId());
        dkCheckInRecord.setSysUserName(appDTO.getUserName());
        dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
        dkCheckInRecord.setClockIn(TimeUtils.parseStr2LocalDateTime(appDTO.getClockIn()));
        dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
        if (null != appDTO.getCheckInStatus()){
            dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
            dkCheckInRecord.setClockInStatus(appDTO.getCheckInStatus());
        }else {
            dkCheckInRecord.setCheckInStatus("1");
            dkCheckInRecord.setClockInStatus("1");
        }
        dkCheckInRecord.setMonth(appDTO.getMonth());
        dkCheckInRecord.setWeek(appDTO.getWeek());
        dkCheckInRecord.setDay(appDTO.getDay());
        dkCheckInRecord.setDescription(appDTO.getDescription());
        dkRecordMapper.insertOrUpdate(dkCheckInRecord);
        return "打卡成功";
    }

    // 判断是否可以签到（给定时间是否在当前时间之前）
    public static boolean canSignIn(String timeStr) {
        // 解析给定的时分秒（格式：HH:mm:ss 或 HH:mm）
        DateTimeFormatter formatter = timeStr.contains(":") ?
            (timeStr.length() > 5 ? DateTimeFormatter.ofPattern("HH:mm:ss") :
                DateTimeFormatter.ofPattern("HH:mm")) :
            DateTimeFormatter.ofPattern("HHmmss");

        LocalTime givenTime = LocalTime.parse(timeStr, formatter);
        LocalTime currentTime = LocalTime.now();

        // 如果当前时间再给定时间之前，则可以签到
        return currentTime.isBefore(givenTime);
    }

    public static boolean allowCheckIn(String timeStr, long maxDifferenceMinutes) {
        try {
            // 解析输入的时间字符串
            DateTimeFormatter formatter = timeStr.contains(":") ?
                (timeStr.length() > 5 ? DateTimeFormatter.ofPattern("HH:mm:ss") :
                    DateTimeFormatter.ofPattern("HH:mm")) :
                DateTimeFormatter.ofPattern("HHmmss");

            LocalTime inputTime = LocalTime.parse(timeStr, formatter);
            LocalTime currentTime = LocalTime.now();

            // 计算时间差（绝对值）
            Duration duration = Duration.between(inputTime, currentTime);
            long diffMinutes = Math.abs(duration.toMinutes());

            // 判断是否超过最大允许时间差
            return diffMinutes <= maxDifferenceMinutes;
        } catch (DateTimeParseException e) {
            System.err.println("时间格式解析错误: " + e.getMessage());
            return false; // 格式错误时默认不允许打卡
        }
    }

    @Override
    public String checkOut(AppDTO appDTO) {
        // 查询打卡配置信息
        AppDTO appDTO1 = dkAttendanceGroupMapper.queryAttendanceGroupBYUserId(appDTO.getUserId());
        // 根据经纬度计算两点之间的距离
//        double distanceKm = GeoDistanceUtil.getDistanceKm(appDTO.getLat(), appDTO.getLng(), appDTO1.getLat(), appDTO1.getLng());
//        if (distanceKm > appDTO.getRadius()){
//            return "超出范围";
//        }

        // 打卡结束时间
        String workEndTime = appDTO1.getWorkEndTime();
        if(workEndTime == null){
            return "系统设置错误";
        }
        // 获取当前天的下班打卡记录
        LambdaQueryWrapper<DkCheckInRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DkCheckInRecord::getSysUserId, appDTO.getUserId());
//        queryWrapper.eq(DkCheckInRecord::getCheckInType, "clockOut");
//        queryWrapper.isNotNull(DkCheckInRecord::getClockOut);
        queryWrapper.orderByDesc(DkCheckInRecord::getCheckInTime);

        // 如果存在下班打卡记录，则更新打卡记录，否则插入打卡记录
        List<DkCheckInRecord> dkCheckInRecords = dkRecordMapper.selectList(queryWrapper);
        DkCheckInRecord dkCheckInRecord;

        if(dkCheckInRecords.size() > 0){
            dkCheckInRecord = dkCheckInRecords.get(0);
            if(dkCheckInRecord.getClockOut() != null){
                dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                dkCheckInRecord.setClockOut(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
                if(null != appDTO.getCheckInStatus()){
                    dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                    dkCheckInRecord.setClockOutStatus(appDTO.getCheckInStatus());
                }else {
                    dkCheckInRecord.setCheckInStatus("5");
                    dkCheckInRecord.setClockOutStatus("5");
                }
                dkCheckInRecord.setDescription(appDTO.getDescription());
                dkRecordMapper.insertOrUpdate(dkCheckInRecord);
                return "更新打卡成功";
            }else{
                // true的时候表示当前时间在给定时间以前，为提前打卡，false的时候正常打卡
                boolean result = canSignIn(workEndTime);
                if(result){
                    // 判断是否允许提前打卡
                    if(appDTO1.getAllowEarly()){
                        // 根据允许的范围进行是否可以打卡判断 true 在允许的范围内， false 不在允许的范围内
                        boolean b = allowCheckIn(workEndTime, appDTO1.getEarlyRange());
                        if(!b){
                            dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                            dkCheckInRecord.setClockOut(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                            dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
                            if(null != appDTO.getCheckInStatus()){
                                dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                                dkCheckInRecord.setClockOutStatus(appDTO.getCheckInStatus());
                            }else{
                                dkCheckInRecord.setCheckInStatus("4");
                                dkCheckInRecord.setClockOutStatus("4");
                            }
                            dkCheckInRecord.setMonth(appDTO.getMonth());
                            dkCheckInRecord.setWeek(appDTO.getWeek());
                            dkCheckInRecord.setDay(appDTO.getDay());
                            dkRecordMapper.insertOrUpdate(dkCheckInRecord);
                            dkCheckInRecord.setDescription(appDTO.getDescription());
                            return "提前打卡";
                        }
                        // 签到成功
                        dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                        dkCheckInRecord.setClockOut(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                        dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
                        if(null != appDTO.getCheckInStatus()){
                            dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                            dkCheckInRecord.setClockOutStatus(appDTO.getCheckInStatus());
                        }else{
                            dkCheckInRecord.setCheckInStatus("2");
                            dkCheckInRecord.setClockOutStatus("2");
                        }
                        dkCheckInRecord.setMonth(appDTO.getMonth());
                        dkCheckInRecord.setWeek(appDTO.getWeek());
                        dkCheckInRecord.setDay(appDTO.getDay());
                        dkCheckInRecord.setDescription(appDTO.getDescription());
                        dkRecordMapper.insertOrUpdate(dkCheckInRecord);
                        return "打卡成功";
                    }

                    dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                    dkCheckInRecord.setClockOut(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                    dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
                    if(null != appDTO.getCheckInStatus()){
                        dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                        dkCheckInRecord.setClockOutStatus(appDTO.getCheckInStatus());
                    }else{
                        dkCheckInRecord.setCheckInStatus("4");
                        dkCheckInRecord.setClockOutStatus("4");
                    }
                    dkCheckInRecord.setMonth(appDTO.getMonth());
                    dkCheckInRecord.setWeek(appDTO.getWeek());
                    dkCheckInRecord.setDay(appDTO.getDay());
                    dkCheckInRecord.setDescription(appDTO.getDescription());
                    dkRecordMapper.insertOrUpdate(dkCheckInRecord);
                    return "提前打卡";
                }

                dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                dkCheckInRecord.setClockOut(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
                if(null != appDTO.getCheckInStatus()){
                    dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                    dkCheckInRecord.setClockOutStatus(appDTO.getCheckInStatus());
                }else{
                    dkCheckInRecord.setCheckInStatus("2");
                    dkCheckInRecord.setClockOutStatus("2");
                }
                dkCheckInRecord.setMonth(appDTO.getMonth());
                dkCheckInRecord.setWeek(appDTO.getWeek());
                dkCheckInRecord.setDay(appDTO.getDay());
                dkCheckInRecord.setDescription(appDTO.getDescription());
                dkRecordMapper.insertOrUpdate(dkCheckInRecord);
                return "打卡成功";
            }

        }else{
            dkCheckInRecord = new DkCheckInRecord();
            dkCheckInRecord.setSysUserId(appDTO.getUserId());
            dkCheckInRecord.setSysUserName(appDTO.getUserName());
            dkCheckInRecord.setMonth(appDTO.getMonth());
            dkCheckInRecord.setWeek(appDTO.getWeek());
            dkCheckInRecord.setDay(appDTO.getDay());
            dkCheckInRecord.setCheckInTime(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
            if(null != appDTO.getCheckInStatus()){
                dkCheckInRecord.setCheckInStatus(appDTO.getCheckInStatus());
                dkCheckInRecord.setClockOutStatus(appDTO.getCheckInStatus());
            }else{
                dkCheckInRecord.setCheckInStatus("4");
                dkCheckInRecord.setClockOutStatus("4");
            }
            dkCheckInRecord.setClockOut(TimeUtils.parseStr2LocalDateTime(appDTO.getClockOut()));
            dkCheckInRecord.setCheckInType(appDTO.getCheckInType());
            dkCheckInRecord.setDescription(appDTO.getDescription());

            dkRecordMapper.insertOrUpdate(dkCheckInRecord);
            return "打卡成功";
        }
    }

    @Override
    public List<DkCheckInRecord> getCurrentDayRecord(AppDTO appDTO) {
        List<DkCheckInRecord> currentDayRecords = dkRecordMapper.getCurrentDayRecord(appDTO.getUserId());
        return currentDayRecords;
    }
}
