using Edu.Common.API;
using Edu.Common.Enum.User;
using Edu.Common.Plugin;
using Edu.Model.CacheModel;
using Edu.Model.Entity.User;
using Edu.Model.Public;
using Edu.Model.ViewModel.User;
using Edu.Repository.User;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VT.FW.DB;

namespace Edu.Module.User
{
    /// <summary>
    /// 考勤处理类
    /// </summary>
    public class AttendanceRecodModule
    {
        private readonly Rb_attendanceRepository respository = new Rb_attendanceRepository();
        private readonly Rb_attendance_wayRepository AWrespository = new Rb_attendance_wayRepository();
        private readonly Rb_workdaysetingRepository WDrespository = new Rb_workdaysetingRepository();
        private readonly Rb_technicaldatesRepository TDrespository = new Rb_technicaldatesRepository();
        private readonly Rb_attendance_recordRepository attendRecordRespository = new Rb_attendance_recordRepository();


        /// <summary>
        /// 获取打卡信息
        /// </summary>
        /// <param name="empId">员工id</param>
        /// <param name="RB_Department_Id">部门id</param>
        /// <param name="date">打卡日期</param>
        /// <returns></returns>
        public JObject GetAttendRecod(int empId, int RB_Department_Id, string date)
        {
            if (Convert.ToDateTime(date).Date > DateTime.Now.Date)
            {
                return null;
            }
            RB_Attendance_Extend attendance = respository.GetAttendanceByEmpId(empId);
            if (attendance != null)
            {
                if (attendance.CreateTime.Date > Convert.ToDateTime(date).Date)
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
            //打卡记录信息
            RB_Attendance_Record_Extend recode = attendRecordRespository.GetAttendRecod(empId, date);
            JObject result = new JObject();
            //先查询特殊日期打卡时间
            //RB_Technicaldates_Extend technical = TDrespository.GetSpecialDate(empId, RB_Department_Id, date);
            var technicalList = TDrespository.GetSpecialDateList(empId, date);// ld 2020-05-25调整
            RB_Technicaldates_Extend technical = null;
            if (technicalList.Any())
            {
                if (technicalList.Where(x => x.EmployeeId > 0).Any() && technicalList.Where(x => x.EmployeeId == empId).Any())
                {
                    technical = technicalList.Where(x => x.EmployeeId == empId).FirstOrDefault();
                }
                else if (technicalList.Where(x => x.RB_Department_Id > 0).Any() && technicalList.Where(x => x.RB_Department_Id == RB_Department_Id).Any())
                {
                    technical = technicalList.Where(x => x.RB_Department_Id == RB_Department_Id).FirstOrDefault();
                }
                else
                {
                    if (technicalList.Where(x => x.RB_Department_Id == 0 && x.EmployeeId == 0).Any())
                    {
                        technical = technicalList.Where(x => x.RB_Department_Id == 0 && x.EmployeeId == 0).FirstOrDefault();
                    }
                }
            }
            if (technical != null)
            {
                if (technical.Type == (int)TechnicalTypeEnum.PunchCard)
                {
                    result["onTime"] = technical.BeOnDutyTime;
                    result["offTime"] = technical.OffDutyTime;
                }
                else
                {
                    //特殊日期不打卡
                    return null;
                }
            }
            else
            {
                //正常打卡日期
                RB_WorkdaySeting_Extend workDay = WDrespository.GetWorkDay(empId, StringHelper.GetWeek(Convert.ToDateTime(date)));
                if (workDay != null)
                {
                    result["onTime"] = workDay.BeOnDutyTime;
                    result["offTime"] = workDay.OffDutyTime;
                }
                else
                {
                    return null;
                }
            }
            if (recode != null)
            {
                if (!string.IsNullOrEmpty(recode.BeOnTime))
                {
                    result["onTime"] = recode.BeOnTime;
                }
                if (!string.IsNullOrEmpty(recode.OffTime))
                {
                    result["offTime"] = recode.OffTime;
                }
                result["id"] = recode.Id;
                result["onStatus"] = (int)recode.BeOnStatus;
                result["onPunshCardTime"] = recode.BeOnDutyTime == null ? "" : recode.BeOnDutyTime.Value.ToString("HH:mm");
                result["onPunshCardAddress"] = recode.BeOnVerifyAddress;
                result["isLackCard"] = recode.BeOnStatus == AttendanceEnum.QK;
                result["offStatus"] = (int)recode.OffStatus;
                result["offPunshCardTime"] = recode.OffDutyTime?.ToString("HH:mm");
                result["offPunshCardAddress"] = recode.OffVerifyAddress;
            }
            else
            {
                result["id"] = 0;
                result["onStatus"] = 0;
                result["onPunshCardTime"] = null;
                result["onPunshCardAddress"] = "";
                result["isLackCard"] = false;
                result["offStatus"] = 0;
                result["offPunshCardTime"] = null;
                result["offPunshCardAddress"] = "";
            }
            string[] tempTypeStr = WFTTemplateTypeEnum.ReissueCard.ToName().Split('|');
            result["cmd"] = tempTypeStr[3];//请求表单cmd
            result["submitCmd"] = tempTypeStr[4];//提交表单cmd
            return result;
        }
        /// <summary>
        /// 验证是否在打卡范围
        /// </summary>
        /// <param name="empId">员工id</param>
        /// <param name="latAndLong">经纬度(维度,经度)</param>
        /// <param name="wifiMac">mac地址</param>
        /// <param name="oldWifiMac">原始wifiMac</param>
        /// <param name="wayList">公司考勤方式</param>
        /// <returns></returns>
        public bool VerifyPunchCard(int empId, string latAndLong, string wifiMac, string oldWifiMac, out List<RB_Attendance_Way_Extend> wayList)
        {
            //verifyAddress合法类型名称
            //type合法类型 1 地点  2  wifi
            wayList = AWrespository.GetWayByEmployeeId(empId);
            return IsRange(empId, latAndLong, wifiMac, oldWifiMac, out int type, out string verifyAddress);
        }

        /// <summary>
        /// App考勤打卡
        /// </summary>
        /// <param name="empId">员工id</param>
        /// <param name="RB_Department_Id">部门id</param>
        /// <param name="latAndLong">经纬度(维度,经度)</param>
        /// <param name="wifiMac">mac地址</param>
        /// <param name="oldWifiMac">原始mac</param>
        /// <param name="phoneId">手机唯一id</param>
        /// <param name="address">打卡地址</param>
        /// <param name="PhoneName">打卡地址</param>
        /// <param name="PunchCardType">1上班,2下班</param>
        /// <param name="isNotVerifyVifi">是否验证wifi</param>
        /// <returns></returns>
        public string PunchCard(int empId, int RB_Department_Id, string latAndLong, string wifiMac, string oldWifiMac, string phoneId, string address, string PhoneName, out int PunchCardType, bool isNotVerifyVifi = false)
        {
            PunchCardType = 1;
            string date = DateTime.Now.ToShortDateString();
            //打卡记录信息
            RB_Attendance_Record_Extend recode = attendRecordRespository.GetAttendRecod(empId, date);
            //根据手机标识码获取打卡记录信息
            RB_Attendance_Record_Extend phoneIdRecode = attendRecordRespository.GetAttendRecodByPhoneId(phoneId, date);
            string onTime = "";
            string offTime = "";
            //先查询特殊日期打卡时间
            #region 获取打卡时间
            //RB_Technicaldates_Extend technical = TDrespository.GetSpecialDate(empId, RB_Department_Id, date);
            var technicalList = TDrespository.GetSpecialDateList(empId, date);// ld 2020-01-25 调整
            RB_Technicaldates_Extend technical = null;
            if (technicalList.Any())
            {
                if (technicalList.Where(x => x.EmployeeId > 0).Any() && technicalList.Where(x => x.EmployeeId == empId).Any())
                {
                    technical = technicalList.Where(x => x.EmployeeId == empId).FirstOrDefault();
                }
                else if (technicalList.Where(x => x.RB_Department_Id > 0).Any() && technicalList.Where(x => x.RB_Department_Id == RB_Department_Id).Any())
                {
                    technical = technicalList.Where(x => x.RB_Department_Id == RB_Department_Id).FirstOrDefault();
                }
                else
                {
                    if (technicalList.Where(x => x.RB_Department_Id == 0 && x.EmployeeId == 0).Any())
                    {
                        technical = technicalList.Where(x => x.RB_Department_Id == 0 && x.EmployeeId == 0).FirstOrDefault();
                    }
                }
            }
            if (technical != null)
            {
                if (technical.Type == (int)TechnicalTypeEnum.PunchCard)
                {
                    onTime = technical.BeOnDutyTime;
                    offTime = technical.OffDutyTime;
                }
                else
                {
                    //特殊日期不打卡
                    return "ok";
                }
            }
            else
            {
                //正常打卡日期
                RB_WorkdaySeting_Extend workDay = WDrespository.GetWorkDay(empId, StringHelper.GetWeek(Convert.ToDateTime(date)));
                if (workDay != null)
                {
                    onTime = workDay.BeOnDutyTime;
                    offTime = workDay.OffDutyTime;
                }
                else
                {
                    return "今天休息,无需打卡";
                }
            }

            #endregion
            #region 验证打卡方式
            //type合法类型 1 地点  2  wifi
            //是否在范围
            int type = 2;
            string verifyAddress = "";
            bool isRange = isNotVerifyVifi ? isNotVerifyVifi : IsRange(empId, latAndLong, wifiMac, oldWifiMac, out type, out verifyAddress);
            if (!isRange && string.IsNullOrWhiteSpace(latAndLong))
            {
                type = 2;
            }
            #endregion

            #region 打卡
            if (recode == null)//上班打卡
            {
                if (phoneIdRecode != null && phoneIdRecode.EmployeeId != empId)
                {
                    return "一台手机一天不能为多个账号打卡";
                }
                else
                {
                    RB_Attendance_Record dbRecord = new RB_Attendance_Record
                    {
                        EmployeeId = empId,
                        BeOnAddress = address,
                        BeOnDutyTime = DateTime.Now,
                        BeOnType = type,
                        BeOnVerifyAddress = verifyAddress
                    };
                    if (dbRecord.BeOnType == 1)
                    {
                        dbRecord.BeOnTargetAddress = latAndLong;
                    }
                    else
                    {
                        dbRecord.BeOnTargetAddress = wifiMac;
                    }
                    dbRecord.PhoneId = phoneId;
                    dbRecord.PhoneName = PhoneName;
                    dbRecord.Date = DateTime.Now;
                    dbRecord.BeOnTime = onTime;
                    //string punchCardTime = dbRecord.BeOnDutyTime.ToShortTimeString();
                    DateTime punchCardDateTime = DateTime.Now;//打卡时间
                    DateTime onDateTime = Convert.ToDateTime(onTime);//上班时间
                    if (isRange)
                    {
                        if (punchCardDateTime.AddMinutes(-1) <= onDateTime)
                        {
                            dbRecord.BeOnStatus = AttendanceEnum.ZC;
                        }
                        else
                        {
                            dbRecord.BeOnStatus = AttendanceEnum.CD;
                            TimeSpan timeSpan = punchCardDateTime - onDateTime;
                            dbRecord.BeLateTime = (int)timeSpan.TotalMinutes;//迟到分钟数
                        }
                    }
                    else
                    {
                        return "不在打卡范围";
                    }
                    attendRecordRespository.Insert(dbRecord);
                    return "ok";
                }
            }
            else
            {
                if (phoneIdRecode != null && phoneIdRecode.Id != recode.Id)
                {
                    return "一台手机一天不能为多个账号打卡";
                }
                else
                {
                    RB_Attendance_Record dbRecord = recode.RefMapperTo<RB_Attendance_Record>();
                    dbRecord.OffAddress = address;
                    if (dbRecord.BeOnType == 1)
                    {
                        dbRecord.OffTargetAddress = latAndLong;
                    }
                    else
                    {
                        dbRecord.OffTargetAddress = wifiMac;
                    }
                    dbRecord.OffDutyTime = DateTime.Now;
                    dbRecord.OffType = type;
                    dbRecord.PhoneId = phoneId;
                    dbRecord.PhoneName = PhoneName;
                    dbRecord.OffVerifyAddress = verifyAddress;
                    dbRecord.OffTime = offTime;
                    //string punchCardTime = dbRecord.BeOnDutyTime.ToShortTimeString();
                    DateTime punchCardDateTime = DateTime.Now;//打卡时间
                    DateTime offDateTime = Convert.ToDateTime(offTime);//下班时间
                    if (isRange)
                    {
                        if (punchCardDateTime >= offDateTime)
                        {
                            dbRecord.OffStatus = AttendanceEnum.ZC;
                            PunchCardType = 2;
                        }
                        else
                        {
                            return "没到下班时间,打卡失败";
                        }
                    }
                    else
                    {
                        return "不在打卡范围";
                    }

                    attendRecordRespository.Update(dbRecord);
                    return "ok";
                }
            }
            #endregion
        }

        /// <summary>
        /// 验证打卡范围
        /// </summary>
        /// <param name="empId"></param>
        /// <param name="latAndLong"></param>
        /// <param name="wifiMac"></param>
        /// <param name="oldWifiMac"></param>
        /// <param name="type">合法类型 1 地点  2  wifi</param>
        /// <param name="verifyAddress">合法类型 名称</param>
        /// <returns></returns>
        private bool IsRange(int empId, string latAndLong, string wifiMac, string oldWifiMac, out int type, out string verifyAddress)
        {
            type = 1;
            verifyAddress = "";
            List<RB_Attendance_Way_Extend> wayList = AWrespository.GetWayByEmployeeId(empId);
            if (wayList != null && wayList.Count() > 0)
            {
                if (!string.IsNullOrWhiteSpace(wifiMac))
                {
                    List<RB_Attendance_Way_Extend> wifiWay = wayList.Where(t => t.Type == (int)AttendWayTypeEnum.Wifi && (t.TargetAddress.ToLower() == wifiMac || t.TargetAddress.ToLower() == oldWifiMac)).ToList();
                    if (wifiWay != null && wifiWay.Count() > 0)
                    {
                        verifyAddress = wifiWay.FirstOrDefault().Name;
                        type = 2;
                        return true;
                    }
                }
                if (!string.IsNullOrWhiteSpace(latAndLong))
                {
                    List<RB_Attendance_Way_Extend> addressList = wayList.Where(t => t.Type == (int)AttendWayTypeEnum.Address).ToList();
                    if (addressList != null && addressList.Count() > 0)
                    {
                        foreach (var item in addressList)
                        {
                            double distance = MapHelper.GetPointDistance(item.TargetAddress, latAndLong);
                            if (distance <= item.Scope)
                            {
                                verifyAddress = item.Name;
                                type = 1;
                                return true;
                            }
                        }
                    }
                }
                return false;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 获取打卡信息统计
        /// </summary>
        /// <param name="empId">员工id</param>
        /// <param name="date">获取日期(年-月-日)</param>
        /// <returns></returns>
        public List<JObject> PunchCardStatistical(int empId, string date)
        {
            //打卡记录信息
            List<RB_Attendance_Record_Extend> recodeList = attendRecordRespository.PunchCardStatistical(empId, date);
            List<JObject> result = new List<JObject>();
            #region 出勤天数
            {
                JObject attendance = new JObject
                {
                    ["name"] = $"出勤天数",
                    ["day"] = $"{recodeList.Count} 天"
                };
                if (recodeList.Count > 0)
                {
                    attendance["color"] = "black";
                }
                else
                {
                    attendance["color"] = "gray";
                }
                List<string> dataList = new List<string>();
                foreach (var item in recodeList)
                {
                    dataList.Add($"{item.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(item.Date)})");
                }
                attendance["dataList"] = JsonConvert.SerializeObject(dataList);
                result.Add(attendance);
            }
            #endregion
            #region 休息天数
            {
                JObject rest = new JObject
                {
                    ["name"] = $"休息天数"
                };
                DateTime searchDate = Convert.ToDateTime(date);
                List<string> dataList = new List<string>();
                if (DateTime.Now.ToString("yyyy-MM") == searchDate.ToString("yyyy-MM"))//本月
                {


                    TimeSpan timeSpan = DateTime.Now - new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                    int days = timeSpan.Days + 1;
                    rest["day"] = $"{days - recodeList.Count()} 天";
                    rest["color"] = "gray";
                    for (int i = 1; i <= days; i++)
                    {
                        DateTime dt = new DateTime(searchDate.Year, searchDate.Month, i);
                        if (recodeList.Where(t => t.Date.ToShortDateString() == dt.ToShortDateString()).Count() == 0)
                        {
                            dataList.Add($"{dt.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(dt.Date)})");
                        }
                    }
                    //foreach (var item in recodeList)
                    //{
                    //    dataList.Add($"{item.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(item.Date)})");
                    //}
                }
                else
                {
                    int days = DateTime.DaysInMonth(searchDate.Year, searchDate.Month);
                    rest["day"] = $"{days - recodeList.Count } 天";
                    rest["color"] = "black";
                    for (int i = 1; i <= days; i++)
                    {
                        DateTime dt = new DateTime(searchDate.Year, searchDate.Month, i);
                        if (recodeList.Where(t => t.Date.ToShortDateString() == dt.ToShortDateString()).Count() == 0)
                        {
                            dataList.Add($"{dt.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(dt.Date)})");
                        }
                    }
                }
                rest["dataList"] = JsonConvert.SerializeObject(dataList);
                result.Add(rest);
            }
            #endregion
            #region 迟到
            {
                JObject late = new JObject
                {
                    ["name"] = $"迟到"
                };
                List<RB_Attendance_Record_Extend> lateRecodeList = recodeList.Where(t => t.BeOnStatus == AttendanceEnum.CD).ToList();
                late["day"] = $"{lateRecodeList.Count} 天";
                if (recodeList.Count > 0)
                {
                    late["color"] = "black";
                }
                else
                {
                    late["color"] = "gray";
                }
                List<string> dataList = new List<string>();
                foreach (var item in lateRecodeList)
                {
                    dataList.Add($"{item.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(item.Date)})");
                }
                late["dataList"] = JsonConvert.SerializeObject(dataList);
                result.Add(late);
            }
            #endregion
            #region 缺卡
            {
                JObject lackOfCard = new JObject
                {
                    ["name"] = $"缺卡"
                };
                List<RB_Attendance_Record_Extend> lackOfCardRecodeList = recodeList.Where(t => t.BeOnStatus != AttendanceEnum.QK && t.OffStatus == AttendanceEnum.QK).ToList();
                lackOfCard["day"] = $"{lackOfCardRecodeList.Count} 天";
                if (lackOfCardRecodeList.Count > 0)
                {
                    lackOfCard["color"] = "black";
                }
                else
                {
                    lackOfCard["color"] = "gray";
                }
                List<string> dataList = new List<string>();
                foreach (var item in lackOfCardRecodeList)
                {
                    dataList.Add($"{item.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(item.Date)})");
                }
                lackOfCard["dataList"] = JsonConvert.SerializeObject(dataList);
                result.Add(lackOfCard);
            }
            #endregion
            #region 旷工
            {
                JObject absenteeism = new JObject
                {
                    ["name"] = $"旷工"
                };
                List<RB_Attendance_Record_Extend> absenteeismRecodeList = recodeList.Where(t => t.BeOnStatus == AttendanceEnum.QK && t.OffStatus == AttendanceEnum.QK).ToList();
                absenteeism["day"] = $"{absenteeismRecodeList.Count} 天";
                if (absenteeismRecodeList.Count > 0)
                {
                    absenteeism["color"] = "red";
                }
                else
                {
                    absenteeism["color"] = "gray";
                }
                List<string> dataList = new List<string>();
                foreach (var item in absenteeismRecodeList)
                {
                    dataList.Add($"{item.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(item.Date)})");
                }
                absenteeism["dataList"] = JsonConvert.SerializeObject(dataList);
                result.Add(absenteeism);
            }
            #endregion
            #region 外勤
            {
                JObject field = new JObject
                {
                    ["name"] = $"外勤"
                };
                List<RB_Attendance_Record_Extend> fieldRecodeList = recodeList.Where(t => t.BeOnStatus == AttendanceEnum.WQ || t.OffStatus == AttendanceEnum.WQ).ToList();
                field["day"] = $"{fieldRecodeList.Count} 天";
                if (fieldRecodeList.Count > 0)
                {
                    field["color"] = "black";
                }
                else
                {
                    field["color"] = "gray";
                }
                List<string> dataList = new List<string>();
                foreach (var item in fieldRecodeList)
                {
                    dataList.Add($"{item.Date.ToShortDateString().Replace("/", "-")}({StringHelper.GetWeekChar(item.Date)})");
                }
                field["dataList"] = JsonConvert.SerializeObject(dataList);
                result.Add(field);
            }
            #endregion
            return result;
        }

        /// <summary>
        /// 获取打卡月历
        /// </summary>
        /// <param name="empId">员工id</param>
        /// <param name="date">获取日期(年-月-日)</param>
        /// <returns></returns>
        public List<JObject> PunchCardCalendar(int empId, string date)
        {
            //打卡记录信息
            List<RB_Attendance_Record_Extend> recodeList = attendRecordRespository.PunchCardStatistical(empId, date);
            List<JObject> result = new List<JObject>();
            DateTime searchDate = Convert.ToDateTime(date);
            List<string> dataList = new List<string>();
            int days = DateTime.DaysInMonth(searchDate.Year, searchDate.Month);
            for (int i = 1; i <= days; i++)
            {
                DateTime dt = new DateTime(searchDate.Year, searchDate.Month, i);
                if (dt.Date < DateTime.Now.Date)
                {
                    JObject data = new JObject
                    {
                        ["day"] = i
                    };
                    RB_Attendance_Record_Extend recode = recodeList.Where(t => t.Date.ToShortDateString() == dt.ToShortDateString()).FirstOrDefault();
                    if (recode != null)
                    {
                        data["id"] = recode.Id;
                        data["rest"] = false;
                        if (recode.BeOnStatus == AttendanceEnum.ZC && recode.OffStatus == AttendanceEnum.ZC)
                        {
                            data["stateColor"] = "#09D49D";//正常
                        }
                        else if (recode.BeOnStatus == AttendanceEnum.CD)
                        {
                            data["stateColor"] = "#FF7D4C";//迟到
                        }
                        else if (recode.BeOnStatus == AttendanceEnum.QK || recode.OffStatus == AttendanceEnum.QK)
                        {
                            data["stateColor"] = "#FF6868";//缺卡
                        }
                        else if (recode.BeOnStatus == AttendanceEnum.WQ || recode.OffStatus == AttendanceEnum.WQ)
                        {
                            data["stateColor"] = "#548DFF";//外勤
                        }
                        else if (recode.BeOnStatus == AttendanceEnum.QJ || recode.OffStatus == AttendanceEnum.QJ)
                        {
                            data["stateColor"] = "#FF7D4C";//请假
                        }
                        else if (recode.BeOnStatus == AttendanceEnum.BK || recode.OffStatus == AttendanceEnum.BK)
                        {
                            data["stateColor"] = "#37CCE7";//补卡
                        }
                        else
                        {
                            data["stateColor"] = "#FF6868";//异常
                        }

                    }
                    else
                    {
                        data["rest"] = true;
                        data["stateColor"] = "#CCCCCC";
                    }
                    result.Add(data);
                }
                else
                {
                    break;
                }
            }
            return result;
        }
    }
}