package jnpf.entity.attendance;

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.enums.attendance.AttendanceTypeEnum;
import jnpf.model.attendance.vo.attendance.OvertimeRuleDetailVo;
import jnpf.util.DateDetail;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.Objects;

/**
 * 考勤组-每日出勤规则
 *
 * @author yanwenfu
 * @create 2023-11-22
 */

@Getter
@Setter
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName(value = "ftb_attendance_daily_rule")
public class FtbAttendanceDailyRule extends SuperBaseEntity.SuperCUDBaseEntity<String> implements Serializable {

    private static final long serialVersionUID = 7692755431988353300L;

    /**
     * 考勤组id
     */
    @TableField(value = "F_GroupId")
    private String groupId;

    /**
     * 班次类型 0全天班次 1上午班次 2下午班次
     */
    @TableField(value = "F_SchedulesType")
    private Integer schedulesType;
    /**
     * 是否自己的考勤组(0未产生借调 1被借调 2借调)
     */
    @TableField(value = "F_SelfGroup")
    private Integer selfGroup;

    /**
     * 班次时段id
     */
    @TableField(value = "F_PeriodId")
    private String periodId;
    /**
     * 班次时段信息
     */
    @TableField(value = "F_PeriodInfo")
    private String periodInfo;
    /**
     * 班次id
     */
    @TableField(value = "F_ShiftId")
    private String shiftId;

    /**
     * 日期
     */
    @TableField(value = "F_Day")
    private Date day;

    /**
     * 用户id
     */
    @TableField(value = "F_UserId")
    private String userId;

    /**
     * 允许迟到(0否 1是)
     */
    @TableField(value = "F_LateEnable")
    private Integer lateEnable;

    /**
     * 允许早退(0否 1是)
     */
    @TableField(value = "F_EarlyEnable")
    private Integer earlyEnable;

    /**
     * 允许休息时间(0否 1是)
     */
    @TableField(value = "F_BreakEnable")
    private Integer breakEnable;

    /**
     * 允许次日下班(0否 1是)
     */
    @TableField(value = "F_NextDayEnable")
    private Integer nextDayEnable;

    /**
     * 打卡开始时间点
     */
    @TableField(value = "F_ClockStartPoint")
    private Date clockStartPoint;

    /**
     * 上班时间点
     */
    @TableField(value = "F_InPoint")
    private Date inPoint;
    /**
     * 是否上班边界覆盖(0未覆盖 1加班覆盖 2借调覆盖 3请假覆盖)
     */
    @TableField(value = "F_InUnbounded")
    private Integer inUnbounded;
    /**
     * 上班是否被外出覆盖(0未覆盖 1覆盖)
     */
    @TableField(value = "F_InStepOutType")
    private Integer inStepOutType;
    /**
     * 上班被外出覆盖申请id
     */
    @TableField(value = "F_InStepOutApplyId")
    private String inStepOutApplyId;
    /**
     * 原上班时间点
     */
    @TableField(value = "F_OriginInPoint")
    private Date originInPoint;

    /**
     * 迟到时间点
     */
    @TableField(value = "F_LatePoint")
    private Date latePoint;
    /**
     * 是否晚走晚到
     */
    @TableField(value = "F_IsLateOutLateIn")
    private Integer isLateOutLateIn;
    /**
     * 原始迟到时间点
     */
    @TableField(value = "F_OriginalLatePoint")
    private Date originalLatePoint;


    /**
     * 上班缺卡时间点
     */
    @TableField(value = "F_InLackPoint")
    private Date inLackPoint;

    public Date getOriginBreakStartPoint() {
        return Objects.nonNull(originBreakStartPoint) ? originBreakStartPoint : breakStartPoint;
    }

    public Date getOriginBreakEndPoint() {
        return Objects.nonNull(originBreakEndPoint)? originBreakEndPoint : breakEndPoint;
    }

    public Date getOriginOutPoint() {
        return Objects.nonNull(originOutPoint)? originOutPoint : outPoint;
    }

    public Date getOriginInPoint() {
        return Objects.nonNull(originInPoint)? originInPoint : inPoint;
    }

    /**
     * 休息开始时间点
     */
    @TableField(value = "F_BreakStartPoint", updateStrategy = FieldStrategy.IGNORED)
    private Date breakStartPoint;
    /**
     * 休息开始时间点
     */
    @TableField(value = "F_OriginBreakStartPoint", updateStrategy = FieldStrategy.IGNORED)
    private Date originBreakStartPoint;

    /**
     * 休息结束时间点
     */
    @TableField(value = "F_BreakEndPoint", updateStrategy = FieldStrategy.IGNORED)
    private Date breakEndPoint;
    /**
     * 休息结束时间点
     */
    @TableField(value = "F_OriginBreakEndPoint", updateStrategy = FieldStrategy.IGNORED)
    private Date originBreakEndPoint;

    /**
     * 早退时间点
     */
    @TableField(value = "F_EarlyPoint")
    private Date earlyPoint;

    /**
     * 下班时间点
     */
    @TableField(value = "F_OutPoint")
    private Date outPoint;
    /**
     * 是否下班边界覆盖(0未覆盖 1加班覆盖 2借调覆盖 3请假覆盖)
     */
    @TableField(value = "F_OutUnbounded")
    private Integer outUnbounded;
    /**
     * 下班是否被外出覆盖(0未覆盖 1覆盖)
     */
    @TableField(value = "F_OutStepOutType")
    private Integer outStepOutType;
    /**
     * 下班被外出覆盖申请id
     */
    @TableField(value = "F_OutStepOutApplyId")
    private String outStepOutApplyId;
    /**
     * 原下班时间点
     */
    @TableField(value = "F_OriginOutPoint")
    private Date originOutPoint;

    /**
     * 下班缺卡时间点
     */
    @TableField(value = "F_OutLackPoint")
    private Date outLackPoint;

    /**
     * 出勤类型(1: 普班, 2: 休, 3: 假, 4: 假（带薪）, 5: 加班)
     */
    @TableField(value = "F_AttendanceType")
    private Integer attendanceType;
    /**
     * 申请id
     */
    @TableField(value = "F_ApplyId")
    private String applyId;
    /**
     * 审核数据展示标识（1 起效，0 失效，2 打卡不展示，3 考勤组剔除人员待删除，9 标识出差，10 标识外出）
     */
    @TableField(value = "F_ApplyViewEnable")
    private Integer applyViewEnable;
    /**
     * 申请事件开始时间
     */
    @TableField(value = "F_ApplyStart")
    private Date applyStart;
    /**
     * 请假天数
     */
    @TableField(value = "F_LeaveDay")
    private BigDecimal leaveDay;
    /**
     * 申请单位（1小时 2日 3半日）
     */
    @TableField(value = "F_ApplyUnit")
    private Integer applyUnit;
    /**
     * 请假申请参数
     */
    @TableField(value = "F_LeaveParam")
    private String leaveParam;


    public void setInPoint(Date inPoint) {
        this.inPoint = inPoint;
        calValidDuration();
    }

    public void calInLackPoint(Date inLackPoint) {
        if (Objects.isNull(inLackPoint)) {
            return;
        }
        this.inLackPoint = inLackPoint.after(this.outPoint) ? this.outPoint : inLackPoint;
    }

    public void calLatePoint(Date latePoint) {
        if (Objects.isNull(latePoint)) {
            return;
        }
        this.latePoint = latePoint.after(this.outPoint) ? this.outPoint : latePoint;
    }

    public void setBreakStartPoint(Date breakStartPoint) {
        this.breakStartPoint = breakStartPoint;
        calValidDuration();
    }

    public void setBreakEndPoint(Date breakEndPoint) {
        this.breakEndPoint = breakEndPoint;
        calValidDuration();
    }

    public void setOutPoint(Date outPoint) {
        this.outPoint = outPoint;
        calValidDuration();
    }

    /**
     * 申请事件结束时间
     */
    @TableField(value = "F_ApplyEnd")
    private Date applyEnd;
    /**
     * 有效时长
     */
    @TableField(value = "F_ValidDuration")
    private Integer validDuration;
    /**
     * 时段工时
     */
    @TableField(value = "F_PeriodWorkDay")
    private BigDecimal periodWorkDay;
    /**
     * 计薪工时
     */
    @TableField(value = "F_PayrollHours")
    private BigDecimal payrollHours;
    /**
     * 原始有效时长
     */
    @TableField(value = "F_OriginValidDuration")
    private Integer originValidDuration;

    public BigDecimal getPayrollHours() {
        if(Objects.nonNull(payrollHours)) {
            return payrollHours;
        }
        if (Objects.isNull(validDuration)) {
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(validDuration).divide(BigDecimal.valueOf(60), 4, RoundingMode.HALF_UP);
    }

    /**
     * 排序
     */
    @TableField(value = "F_Sort")
    private Integer sort;
    /**
     * 是否固定班 3自动排休调休上班 2为划线排班
     */
    @TableField(value = "F_FixedMark")
    private Integer fixedMark;

    /** 隐藏(0:不隐藏, 1:上班隐藏) */
    @TableField(exist = false)
    private String inHideStatus = "0";
    /** 隐藏(0:不隐藏, 1:下班隐藏) */
    @TableField(exist = false)
    private String outHideStatus = "0";
    /** 上班无需打卡(true:是, false:否) */
    @TableField(exist = false)
    private boolean onWorkIgnore = false;
    /** 下班无需打卡(true:是, false:否) */
    @TableField(exist = false)
    private boolean offWorkIgnore = false;
    /** 行号 */
    @TableField(exist = false)
    private Integer rn;
    /** 消息(离岗、回岗) */
    @TableField(exist = false)
    private String msg;
    /** 加班规则 */
    @TableField(exist = false)
    private OvertimeRuleDetailVo overtimeRuleDetail;
    /** 无审批加班 */
    @TableField(exist = false)
    private Integer overtime = 0;
    /** 目标日期 */
    @TableField(exist = false)
    private String targetDate;
    /** 实际日期(目标日期/目标日期-1) */
    @TableField(exist = false)
    private String queryDate;

    @TableField(exist = false)
    private Boolean isInsert = Boolean.FALSE;
    @TableField(exist = false)
    private Boolean isDelete = Boolean.FALSE;
    public void delete(){
        this.isDelete = true;
    }

    public void calValidDuration() {
        if (Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.LEAVE.getCode()) || Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.ORDINARY.getCode())|| Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.REST.getCode()) || Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.WORKOVERTIME.getCode())) {
            if (Objects.isNull(this.getInPoint())) {
                return;
            }
            if (Objects.isNull(this.getOutPoint())) {
                return;
            }
            this.setValidDuration(DateDetail.calculateMinuteDiff(this.getInPoint(), this.getOutPoint()));
            if (Objects.isNull(this.getBreakEnable()) || this.getBreakEnable() == 0) {
                return;
            }
            if (Objects.isNull(this.getBreakStartPoint())) {
                return;
            }
            if (Objects.isNull(this.getBreakEndPoint())) {
                return;
            }
            this.setValidDuration(this.getValidDuration() - DateDetail.calculateMinuteDiff(this.getBreakStartPoint(), this.getBreakEndPoint()));
        }
    }
    public void calOriginValidDuration() {
        if (Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.LEAVE.getCode()) || Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.ORDINARY.getCode())|| Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.REST.getCode()) || Objects.equals(this.getAttendanceType(), AttendanceTypeEnum.WORKOVERTIME.getCode())) {
            if (Objects.isNull(this.getOriginInPoint())) {
                return;
            }
            if (Objects.isNull(this.getOriginOutPoint())) {
                return;
            }
            this.setOriginValidDuration(DateDetail.calculateMinuteDiff(this.getOriginInPoint(), this.getOriginOutPoint()));
            if (Objects.isNull(this.getBreakEnable()) || this.getBreakEnable() == 0) {
                return;
            }
            if (Objects.isNull(this.getOriginBreakStartPoint())) {
                return;
            }
            if (Objects.isNull(this.getOriginBreakEndPoint())) {
                return;
            }
            this.setOriginValidDuration(this.getOriginValidDuration() - DateDetail.calculateMinuteDiff(this.getOriginBreakStartPoint(), this.getOriginBreakEndPoint()));
        }
    }


    public void insertTrue() {
        this.isInsert = Boolean.TRUE;
    }
}
