using System;
using System.Collections.Generic;
using System.Globalization;
using IgnoreOPS;
using UnityEngine;
using Random = System.Random;

namespace ChillConnect
{
    public class RankSystemMgr : BaseInterfaceManager<RankSystemMgr>
    {

        public string[] time_slot = { "00:00-2:00", "2:00-9:00", "9:00-19:00", "19:00-23:59" };
        public int hourTime = 3 * 60; // 3 hour
        public int[] basePoint = { 0, 10 };
        public int RobotNum = 500;
        // public long selfUid = 12345678;
        public int[] RobotBasicScore = { 10, 20 };
        public int addPoints;
        public int addPointsUI;

        public List<RankRewards> hourRewardList;
        public List<RankRewards> dayRewardList;
        public List<RankRewards> weekRewardList;

        public void checkUsers()
        {
            time_slot = ConfigSystem.GetConfig<CommonModel>().TimeSlot;
            hourTime = ConfigSystem.GetConfig<CommonModel>().HourTime * 60;
            basePoint = ConfigSystem.GetConfig<CommonModel>().basePoint;
            // basePoint[0] = basePoint[1];
            RobotNum = ConfigSystem.GetConfig<CommonModel>().RobotNum;

            hourRewardList = ConfigSystem.GetConfig<RankHourRewardsModel>().DataList;
            dayRewardList = ConfigSystem.GetConfig<RankDayRewardsModel>().DataList;
            weekRewardList = ConfigSystem.GetConfig<RankWeekRewardsModel>().DataList;

            if (SaveData.GetRankData().users == null || SaveData.GetRankData().users.Count == 0)
            {
                CreatUsers();
            }
            upRewardAndRank();
        }

        public void upRewardAndRank()
        {
           // upRankReward();
           // updateRank();

        }

        private void CreatUsers()
        {
            string name = GameHelper.GetUserName();
            SaveData.GetRankData().users.Clear();
            for (int i = 0; i < RobotNum; i++)
            {
                UserData user = new UserData();
                user.uid = i + 1;
                user.name = GenerateName(name.Length);
                user.bonus = 0;
                user.headId = _random.Next(1, 5);
                user.hourPoints = 0;
                user.dayPoints = 0;
                user.weekPoints = 0;
                user.lastHourPoints = 0;
                user.lastDayPoints = 0;
                user.lastWeekPoints = 0;
                // user.add_points_time = new int[time_slot.Length];
                // user.remaining_time = new int[time_slot.Length];

                user.add_points_time = new int[7][];
                user.remaining_time = new int[7][];
                for (int j = 0; j < 7; j++)
                {
                    user.add_points_time[j] = new int[time_slot.Length];
                    user.remaining_time[j] = new int[time_slot.Length];
                }

                for (int k = 0; k < 7; k++)
                {
                    for (int j = 0; j < time_slot.Length; j++)
                    {
                        int value = GetTimeDifferenceInMinutes(time_slot[j]);
                        if (value > 10)
                        {
                            user.add_points_time[k][j] = _random.Next(10, value);
                        }
                        else
                        {
                            user.add_points_time[k][j] = _random.Next(0, value);
                        }
                        user.remaining_time[k][j] = user.add_points_time[k][j];
                    }
                }

                SaveData.GetRankData().users.Add(user);
            }

            // 自己的数据
            SaveData.GetRankData().selfUser = new UserData();
            // if (GameHelper.IsGiftSwitch())
            // {
            SaveData.GetRankData().selfUser.uid = GameHelper.GetLoginModel().Uid;
            // }
            // else
            // {
            //     SaveData.GetRankData().selfUser.uid = selfUid;
            // }
            SaveData.GetRankData().selfUser.name = GameHelper.GetUserName();
            SaveData.GetRankData().selfUser.bonus = 0;
            SaveData.GetRankData().selfUser.headId = DataMgr.PlayerAvatarId.Value;
            SaveData.GetRankData().selfUser.points = 0;
            SaveData.GetRankData().selfUser.hourPoints = 0;
            SaveData.GetRankData().selfUser.dayPoints = 0;
            SaveData.GetRankData().selfUser.weekPoints = 0;


            SaveData.SaveRankFunc();
        }

        public void updateRank()
        {
            // SaveData.GetSaveObject().lastLoginTime = 1747056321 + (long)(86400 * 0.5);
            long curTime = GameHelper.GetNowTime();
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(curTime);
            DateTime curLocalTime = utcTime.ToLocalTime();
            int hour = curLocalTime.Hour;
            int minute = curLocalTime.Minute;
            DayOfWeek dayOfWeek = curLocalTime.DayOfWeek;

            if (SaveData.GetSaveObject().lastLoginTime != 0)
            {
                utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(SaveData.GetSaveObject().lastLoginTime);
                DateTime lastLocalTime = utcTime.ToLocalTime();
                int lastHour = lastLocalTime.Hour;
                int lastMinute = lastLocalTime.Minute;
                DayOfWeek lastDayOfWeek = lastLocalTime.DayOfWeek;
                bool sameWeek = isInSameWeek(curLocalTime, lastLocalTime);
                if (sameWeek)
                {
                    if (dayOfWeek != lastDayOfWeek)
                    {
                        clearAndCreateData(dayOfWeek);
                    }
                    else
                    {
                        upLastToCurPoints(dayOfWeek, lastHour, lastMinute, hour, minute);
                    }
                }
                else
                {
                    CreatUsers();
                    clearAndCreateData(dayOfWeek);


                }
            }
            else
            {
                clearAndCreateData(dayOfWeek);
            }

            upSelfPoints();

            SaveData.GetSaveObject().lastLoginTime = GameHelper.GetNowTime();
            SaveData.SaveRankFunc();
        }

        // 检查是否有奖励
        public void upRankReward()
        {
            long curTime = GameHelper.GetNowTime();
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(curTime);
            DateTime curLocalTime = utcTime.ToLocalTime();
            int hour = curLocalTime.Hour;
            int minute = curLocalTime.Minute;
            int day = curLocalTime.Day;
            int year = curLocalTime.Year;
            int month = curLocalTime.Month;
            DayOfWeek dayOfWeek = curLocalTime.DayOfWeek;
            int round = hour / (hourTime / 60);

            if (SaveData.GetSaveObject().lastLoginTime != 0)
            {
                utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(SaveData.GetSaveObject().lastLoginTime);
                DateTime lastLocalTime = utcTime.ToLocalTime();
                int lastHour = lastLocalTime.Hour;
                int lastMinute = lastLocalTime.Minute;
                int lastDay = lastLocalTime.Day;
                int lastyear = curLocalTime.Year;
                int lastmonth = curLocalTime.Month;
                DayOfWeek lastDayOfWeek = lastLocalTime.DayOfWeek;
                int lastRound = lastHour / (hourTime / 60);
                // 不同一周
                List<UserData> users = SaveData.GetRankData().users;
                if (!isInSameWeek(curLocalTime, lastLocalTime))
                {
                    for (int i = 0; i < users.Count; i++)
                    {
                        int points1 = getWeekPoints(users[i]);
                        users[i].lastWeekPoints = points1;
                    }

                    SaveData.GetRankData().selfUser.lastWeekPoints = SaveData.GetRankData().selfUser.weekPoints;
                    var temp = SaveData.GetRankData().selfUser.lastWeekPoints;

                    SaveData.GetRankData().users.Add(SaveData.GetRankData().selfUser);
                    SaveData.GetRankData().users.Sort((a, b) => b.lastWeekPoints.CompareTo(a.lastWeekPoints));

                    for (int i = 0; i < weekRewardList.Count; i++)
                    {
                        // SaveData.GetRankData().users[i].bonus = weekRewardList[i].award;
                        if (SaveData.GetRankData().users[i].uid == SaveData.GetRankData().selfUser.uid)
                        {
                            RankRewardData data = new RankRewardData();
                            data.rank = i + 1;
                            data.type = rankType.week;
                            data.bonus = weekRewardList[i].award;
                            data.time = getLastLoginWeekEndTime();
                            SaveData.GetRankData().rankRewardData.Insert(0, data);
                            SaveData.GetRankData().selfUser.lastWeekPoints = 0;
                            break;
                        }
                    }
                    SaveData.GetRankData().users.Remove(SaveData.GetRankData().selfUser);
                }

                // 不同一天
                if (year != lastyear || month != lastmonth || day != lastDay)
                {
                    int index = getIndexInTimeSlot(lastHour, lastMinute);
                    for (int i = 0; i < users.Count; i++)
                    {
                        users[i].lastDayPoints = getDayPoints(users[i], lastDayOfWeek, index);
                    }

                    SaveData.GetRankData().selfUser.lastDayPoints = SaveData.GetRankData().selfUser.dayPoints;

                    SaveData.GetRankData().users.Add(SaveData.GetRankData().selfUser);
                    SaveData.GetRankData().users.Sort((a, b) => b.lastDayPoints.CompareTo(a.lastDayPoints));
                    for (int i = 0; i < dayRewardList.Count; i++)
                    {
                        // SaveData.GetRankData().users[i].bonus = dayRewardList[i].award;
                        if (SaveData.GetRankData().users[i].uid == SaveData.GetRankData().selfUser.uid)
                        {
                            RankRewardData data = new RankRewardData();
                            data.rank = i + 1;
                            data.type = rankType.day;
                            data.bonus = dayRewardList[i].award;
                            data.time = getLastLoginDateTime();
                            SaveData.GetRankData().rankRewardData.Insert(0, data);
                            SaveData.GetRankData().selfUser.lastDayPoints = 0;
                            break;
                        }
                    }
                    SaveData.GetRankData().users.Remove(SaveData.GetRankData().selfUser);
                }

                // 不同时段
                if (day != lastDay || round != lastRound)
                {
                    int index = getIndexInTimeSlot(lastHour, lastMinute);
                    for (int i = 0; i < users.Count; i++)
                    {
                        users[i].lastHourPoints = getRoundPoints(users[i], lastDayOfWeek, index);
                    }

                    SaveData.GetRankData().selfUser.lastHourPoints = SaveData.GetRankData().selfUser.hourPoints;
                    var temp = SaveData.GetRankData().selfUser.lastHourPoints;

                    SaveData.GetRankData().users.Add(SaveData.GetRankData().selfUser);
                    SaveData.GetRankData().users.Sort((a, b) => b.lastHourPoints.CompareTo(a.lastHourPoints));
                    var temp2 = SaveData.GetRankData().users;
                    for (int i = 0; i < hourRewardList.Count; i++)
                    {
                        // SaveData.GetRankData().users[i].bonus = hourRewardList[i].award;
                        if (SaveData.GetRankData().users[i].uid == SaveData.GetRankData().selfUser.uid)
                        {
                            RankRewardData data = new RankRewardData();
                            data.rank = i + 1;
                            data.type = rankType.hour;
                            data.bonus = hourRewardList[i].award;
                            data.time = getLastLoginRoundTime();
                            SaveData.GetRankData().rankRewardData.Insert(0, data);
                            SaveData.GetRankData().selfUser.lastHourPoints = 0;
                            break;
                        }
                    }
                    SaveData.GetRankData().users.Remove(SaveData.GetRankData().selfUser);
                }
            }

            remove30DaysData();

            if (SaveData.GetRankData().rankRewardData.Count > 0)
            {
                GameDispatcher.Instance.Dispatch(GameMsg.RefreshHallRank);
            }
        }

        // 获取排行榜
        public List<UserData> getRankData(rankType type)
        {
            List<UserData> originalUsers = SaveData.GetRankData().users;
            List<UserData> rankList = new List<UserData>(originalUsers);
            rankList.Add(SaveData.GetRankData().selfUser);
            for (int i = 0; i < rankList.Count; i++)
            {
                rankList[i].bonus = 0;
            }
            if (type == rankType.hour)
            {
                rankList.Sort((a, b) => b.hourPoints.CompareTo(a.hourPoints));
                for (int i = 0; i < hourRewardList.Count; i++)
                {
                    if (i >= rankList.Count)
                    {
                        break;
                    }
                    rankList[i].bonus = hourRewardList[i].award;
                }
            }
            else if (type == rankType.day)
            {
                rankList.Sort((a, b) => b.dayPoints.CompareTo(a.dayPoints));
                for (int i = 0; i < dayRewardList.Count; i++)
                {
                    if (i >= rankList.Count)
                    {
                        break;
                    }
                    rankList[i].bonus = dayRewardList[i].award;
                }
            }
            else if (type == rankType.week)
            {
                rankList.Sort((a, b) => b.weekPoints.CompareTo(a.weekPoints));
                for (int i = 0; i < weekRewardList.Count; i++)
                {
                    if (i >= rankList.Count)
                    {
                        break;
                    }
                    rankList[i].bonus = weekRewardList[i].award;
                }
            }

            return rankList;
        }

        // 更新排行榜
        public void clearAndCreateData(DayOfWeek dayOfWeek)
        {
            List<UserData> users = SaveData.GetRankData().users;
            for (int i = 0; i < users.Count; i++)
            {
                int points1 = getMondayToCurDayPoints(users[i], dayOfWeek);
                int[] pointsArr = getCurDayPoints(users[i]);
                users[i].weekPoints = points1 + pointsArr[0];
                users[i].dayPoints = pointsArr[0];
                users[i].hourPoints = pointsArr[1];
            }
        }

        // 更新同一天内上次到本次登陆的积分
        public int upLastToCurPoints(DayOfWeek day_of_week, int lastHour, int lastMinute, int hour, int minute)
        {
            int dayOfWeek = (int)day_of_week;
            if (day_of_week == DayOfWeek.Sunday)
            {
                dayOfWeek = 7;
            }

            int index = getIndexInTimeSlot(hour, minute);
            int lastLoginIndex = getIndexInTimeSlot(lastHour, lastMinute);
            int round = hour / (hourTime / 60);
            int last_round = lastHour / (hourTime / 60);
            int perTime = getInPreSlotTime(index, hour);
            List<UserData> users = SaveData.GetRankData().users;
            int totalTime = GetTimeDifferenceInMinutes(time_slot[lastLoginIndex]);
            for (int i = 0; i < users.Count; i++)
            {
                int points = 0;
                for (int j = 0; j < users[i].add_points_time.Length; j++)
                {
                    if (j + 1 == dayOfWeek)
                    {
                        string[] parts = time_slot[index].Split('-');
                        string startTimeStr = parts[0].Trim();
                        string curHM = $"{hour:D2}:{minute:D2}";
                        string curTimeDifference = startTimeStr + "-" + curHM;
                        string lastHM = $"{lastHour:D2}:{lastMinute:D2}";
                        string lastTimeDifference = startTimeStr + "-" + lastHM;
                        int passTime = GetTimeDifferenceInMinutes(curTimeDifference);
                        int randBasePoint = _random.Next(basePoint[0], basePoint[1]);
                        if (lastLoginIndex == index)
                        {
                            int lastPassTime = GetTimeDifferenceInMinutes(lastTimeDifference);
                            int dif = passTime - lastPassTime;

                            if (dif < 0)
                            {
                                dif = 0;
                            }
                            int randomMin = 0;
                            if (totalTime - passTime < users[i].remaining_time[dayOfWeek - 1][index])
                            {
                                randomMin = users[i].remaining_time[dayOfWeek - 1][index] - (totalTime - passTime);
                            }
                            int randomMax = passTime > users[i].remaining_time[dayOfWeek - 1][index] ? users[i].remaining_time[dayOfWeek - 1][index] : passTime;
                            randomMax = randomMax > dif ? dif : randomMax;
                            if (randomMin > randomMax)
                            {
                                randomMax = randomMin + 1;
                            }
                            int value = _random.Next(randomMin, randomMax + 1);

                            points += value * randBasePoint;
                            users[i].remaining_time[dayOfWeek - 1][index] -= value;
                            if (users[i].remaining_time[dayOfWeek - 1][index] < 0)
                            {
                                users[i].remaining_time[dayOfWeek - 1][index] = 0;
                            }


                            if (round == last_round)
                            {
                                users[i].hourPoints += points;
                            }
                            else
                            {
                                int curRoundStartTime = round * hourTime / 60;
                                string curRoundStartTimeHM = $"{curRoundStartTime:D2}:00";
                                string DifferenceTime = curRoundStartTimeHM + "-" + curHM;
                                int curRoundPassTime = GetTimeDifferenceInMinutes(DifferenceTime);
                                if (curRoundPassTime == 0 || dif == 0)
                                {
                                    users[i].hourPoints = 0;
                                }
                                else
                                {
                                    int curRoundActiveTime = (int)((decimal)curRoundPassTime / dif * value);
                                    users[i].hourPoints = curRoundActiveTime * randBasePoint;
                                }

                            }

                            users[i].weekPoints += points;
                            users[i].dayPoints += points;

                        }
                        else
                        {
                            if (round == last_round)
                            {
                                users[i].weekPoints += users[i].remaining_time[dayOfWeek - 1][lastLoginIndex] * randBasePoint;
                                users[i].dayPoints += users[i].remaining_time[dayOfWeek - 1][lastLoginIndex] * randBasePoint;
                                users[i].hourPoints += users[i].remaining_time[dayOfWeek - 1][lastLoginIndex] * randBasePoint;
                                users[i].remaining_time[dayOfWeek - 1][lastLoginIndex] = 0;
                                int value = _random.Next(0, passTime);
                                if (users[i].remaining_time[dayOfWeek - 1][index] - value > 0)
                                {
                                    points += value * randBasePoint;
                                    users[i].remaining_time[dayOfWeek - 1][index] -= value;
                                    if (users[i].remaining_time[dayOfWeek - 1][index] < 0)
                                    {
                                        users[i].remaining_time[dayOfWeek - 1][index] = 0;
                                    }
                                }
                                else
                                {
                                    points += users[i].remaining_time[dayOfWeek - 1][index] * randBasePoint;
                                    users[i].remaining_time[dayOfWeek - 1][index] = 0;
                                }
                                users[i].hourPoints += points;
                                users[i].weekPoints += points;
                                users[i].dayPoints += points;
                            }
                            else
                            {
                                // todo bug，周和天多加了，应该算上一次到本次的积分
                                int[] pointsArr = getCurDayPoints(users[i]);
                                users[i].weekPoints += pointsArr[0];
                                users[i].dayPoints += pointsArr[0];
                                users[i].hourPoints = pointsArr[1];
                            }
                        }
                    }
                }
            }

            return 0;
        }

        // 获取一周的积分
        public int getWeekPoints(UserData user)
        {
            int points = 0;
            for (int i = 0; i < user.add_points_time.Length; i++)
            {
                for (int j = 0; j < user.add_points_time[i].Length; j++)
                {
                    int randBasePoint = _random.Next(basePoint[0], basePoint[1]);
                    points += user.add_points_time[i][j] * randBasePoint;
                }

            }
            return points;
        }

        // 获取一天的积分
        public int getDayPoints(UserData user, DayOfWeek dayOfWeek, int lastIndex)
        {
            int points = 0;
            int days = (int)dayOfWeek;
            if (dayOfWeek == DayOfWeek.Sunday)
            {
                days = 7;
            }

            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(SaveData.GetSaveObject().lastLoginTime);
            DateTime lastLocalTime = utcTime.ToLocalTime();
            int lastHour = lastLocalTime.Hour;
            int lastMinute = lastLocalTime.Minute;
            int randBasePoint = _random.Next(basePoint[0], basePoint[1]);

            points += user.dayPoints + user.remaining_time[days - 1][lastIndex] * randBasePoint;

            for (int i = lastIndex; i < user.remaining_time[days - 1].Length; i++)
            {
                randBasePoint = _random.Next(basePoint[0], basePoint[1]);
                points += user.remaining_time[days - 1][i] * randBasePoint;
            }

            // for (int i = 0; i < user.add_points_time.Length; i++)
            // {
            //     if ((i + 1) == days)
            //     {
            //         for (int j = 0; j < user.add_points_time[i].Length; j++)
            //         {
            //             randBasePoint = _random.Next(basePoint[0], basePoint[1]);
            //             points += user.add_points_time[i][j] * randBasePoint;
            //         }
            //     }
            // }
            return points;
        }

        // 获取小时排行榜积分
        public int getRoundPoints(UserData user, DayOfWeek dayOfWeek, int index)
        {
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(SaveData.GetSaveObject().lastLoginTime);
            DateTime lastLocalTime = utcTime.ToLocalTime();
            int lastHour = lastLocalTime.Hour;
            int lastMinute = lastLocalTime.Minute;

            int lastRound = lastHour / (hourTime / 60);
            int curRoundStartTime = lastRound * hourTime / 60;
            string curRoundStartTimeHM = $"{curRoundStartTime:D2}:00";
            int endTime = curRoundStartTime + hourTime / 60;
            string curRoundEndHM = $"{endTime:D2}:00";
            string DifferenceTime = curRoundStartTimeHM + "-" + curRoundEndHM;
            if (endTime >= 24)
            {
                DifferenceTime = curRoundStartTimeHM + "-" + "23:59";
            }
            int RoundTime = GetTimeDifferenceInMinutes(DifferenceTime);
            string roundPassTimeStr = curRoundStartTimeHM + "-" + $"{lastHour:D2}:{lastMinute:D2}";
            int roundPassTime = GetTimeDifferenceInMinutes(roundPassTimeStr);
            int round_remain_time = RoundTime - roundPassTime;

            string[] parts = time_slot[index].Split('-');
            string slotEndTime = parts[1].Trim();
            string curToSlotEndTimeStr = $"{lastHour:D2}:{lastMinute:D2}" + "-" + slotEndTime;
            int curToSlotEndTime = GetTimeDifferenceInMinutes(curToSlotEndTimeStr);

            int days = (int)dayOfWeek;
            if (dayOfWeek == DayOfWeek.Sunday)
            {
                days = 7;
            }
            int consumeTime = 0;
            int points = 0;
            int randBasePoint = _random.Next(basePoint[0], basePoint[1]);
            if (curToSlotEndTime == 0)
            {
                consumeTime = user.remaining_time[days - 1][index];
                points = user.hourPoints + consumeTime * randBasePoint;
            }
            else
            {
                consumeTime = (int)((decimal)user.remaining_time[days - 1][index] / curToSlotEndTime * round_remain_time);
                points = user.hourPoints + (int)((decimal)user.remaining_time[days - 1][index] / curToSlotEndTime * round_remain_time * randBasePoint);
            }


            user.remaining_time[days - 1][index] -= consumeTime;
            if (user.remaining_time[days - 1][index] < 0)
            {
                user.remaining_time[days - 1][index] = 0;
            }

            return points;
        }

        // 获取周一到当前周几整天的积分
        public int getMondayToCurDayPoints(UserData user, DayOfWeek dayOfWeek)
        {
            int points = 0;
            int days = (int)dayOfWeek;
            if (dayOfWeek == DayOfWeek.Sunday)
            {
                days = 7;
            }
            for (int i = 0; i < user.add_points_time.Length; i++)
            {
                if (i + 1 < days)
                {
                    for (int j = 0; j < user.add_points_time[i].Length; j++)
                    {
                        int randBasePoint = _random.Next(basePoint[0], basePoint[1]);
                        points += user.add_points_time[i][j] * randBasePoint;
                        user.remaining_time[i][j] = 0;
                    }
                }
            }

            return points;
        }

        // 获取当天的积分
        public int[] getCurDayPoints(UserData user)
        {
            int points = 0;
            int hourPoints = 0;
            int[] result = new int[2];
            long curTime = GameHelper.GetNowTime();
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(curTime);
            DateTime curLocalTime = utcTime.ToLocalTime();
            int day = curLocalTime.Day;
            int hour = curLocalTime.Hour;
            int minute = curLocalTime.Minute;
            int dayOfWeek = (int)curLocalTime.DayOfWeek;
            if (curLocalTime.DayOfWeek == DayOfWeek.Sunday)
            {
                dayOfWeek = 7;
            }


            int index = getIndexInTimeSlot(hour, minute);
            int perTime = getInPreSlotTime(index, hour);

            for (int i = 0; i < user.add_points_time.Length; i++)
            {
                if (i + 1 == dayOfWeek)
                {
                    for (int j = 0; j <= index; j++)
                    {
                        int totalTime = GetTimeDifferenceInMinutes(time_slot[j]);
                        if (totalTime < 0)
                        {
                            totalTime = 0;
                            Debug.Log("config error!!!");
                        }
                        int randBasePoint = _random.Next(basePoint[0], basePoint[1]);
                        if (j < index)
                        {
                            points += user.add_points_time[i][j] * randBasePoint;
                            if (perTime > 0 && j == index - 1)
                            {
                                hourPoints += (int)Math.Round((decimal)perTime * 60 / totalTime * user.add_points_time[i][j]) * randBasePoint;
                            }
                            user.remaining_time[i][j] = 0;
                        }
                        else
                        {
                            string[] parts = time_slot[index].Split('-');
                            string startTimeStr = parts[0].Trim();
                            string[] hours = startTimeStr.Split(':');
                            int startHour = int.Parse(hours[0]);
                            int startMinute = int.Parse(hours[1]);
                            string curHM = $"{hour:D2}:{minute:D2}";
                            string curTimeDifference = startTimeStr + "-" + curHM;
                            int passTime = GetTimeDifferenceInMinutes(curTimeDifference);
                            int randomMin = 0;
                            if (totalTime - passTime < user.remaining_time[i][j])
                            {
                                randomMin = user.remaining_time[i][j] - (totalTime - passTime);
                            }
                            if (startMinute == minute && startHour == hour)
                            {
                                passTime = 0;
                            }
                            int randomMax = passTime > user.remaining_time[i][j] ? user.remaining_time[i][j] : passTime;
                            if (randomMin > randomMax)
                            {
                                randomMax = randomMin + 1;
                            }
                            int value = _random.Next(randomMin, randomMax + 1);


                            // 随机到的时间是否全在小时榜时间内
                            int inHourTime = getInHourTime(index, hour, minute, value);

                            hourPoints += inHourTime * randBasePoint;
                            user.remaining_time[i][j] -= value;
                            if (user.remaining_time[i][j] < 0)
                            {
                                user.remaining_time[i][j] = 0;
                            }
                            points += value * randBasePoint;
                        }
                    }
                }
            }

            result[0] = points;
            result[1] = hourPoints;

            return result;
        }

        // 判断在time_slot哪个时间段
        public int getIndexInTimeSlot(int hour, int minute)
        {
            int index = 0;
            if (hour == 23)
            {
                index = time_slot.Length - 1;
            }
            else
            {
                for (int j = 0; j < time_slot.Length; j++)
                {
                    string[] parts = time_slot[j].Split('-');
                    string startTimeStr = parts[0].Trim();
                    string endTimeStr = parts[1].Trim();
                    string[] startParts = startTimeStr.Split(':');
                    string[] endParts = endTimeStr.Split(':');
                    if (hour >= int.Parse(startParts[0]) && hour < int.Parse(endParts[0]))
                    {
                        index = j;
                        break;
                    }
                }
            }
            return index;
        }

        public int getInPreSlotTime(int index, int hour)
        {
            string[] parts = time_slot[index].Split('-');
            string startTimeStr = parts[0].Trim();
            string endTimeStr = parts[1].Trim();
            string[] startParts = startTimeStr.Split(':');
            string[] endParts = endTimeStr.Split(':');

            int pass_hour = hour % (hourTime / 60);
            int value = hour - int.Parse(startParts[0]);
            int result = 0;
            if (value < pass_hour)
            {
                result = pass_hour - value;
            }
            return result;
        }

        public int getInHourTime(int index, int hour, int minute, int seed)
        {
            int pass_hour = hour % (hourTime / 60);
            int startTime = hour - pass_hour;
            int min = 0;
            string starHM = $"{startTime:D2}:{min:D2}";
            string endHM = $"{startTime + (hourTime / 60):D2}:{min:D2}";
            string curHM = $"{hour:D2}:{minute:D2}";
            string startToCurStr = starHM + "-" + curHM;
            int hourStartToCur = GetTimeDifferenceInMinutes(startToCurStr);

            string[] parts = time_slot[index].Split('-');
            string startTimeStr = parts[0].Trim();
            string endTimeStr = parts[1].Trim();
            string curTimeDifference = startTimeStr + "-" + curHM;
            int passTime = GetTimeDifferenceInMinutes(curTimeDifference);

            if (hourStartToCur >= passTime)
            {
                return seed;
            }

            int resulte = 0;
            if (hourStartToCur > seed)
            {
                resulte = seed;
            }
            else
            {
                if (passTime <= 0)
                {
                    resulte = 0;
                }
                else
                {
                    resulte = seed - (int)Math.Round((decimal)seed / passTime * (passTime - hourStartToCur));
                }
            }
            return resulte;
        }

        public bool hasPreSlotTime(int index, int hour)
        {
            string[] parts = time_slot[index].Split('-');
            string startTimeStr = parts[0].Trim();
            string endTimeStr = parts[1].Trim();
            string[] startParts = startTimeStr.Split(':');
            string[] endParts = endTimeStr.Split(':');
            if (int.Parse(startParts[0]) < hour)
            {
                return false;
            }

            return true;
        }

        public bool isInSameWeek(DateTime date1, DateTime date2)
        {
            // 创建 GregorianCalendar 实例
            Calendar cal = CultureInfo.InvariantCulture.Calendar;

            // 获取两个日期的年份和周数
            int year1 = cal.GetYear(date1);
            int year2 = cal.GetYear(date2);
            int week1 = cal.GetWeekOfYear(date1, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
            int week2 = cal.GetWeekOfYear(date2, CalendarWeekRule.FirstDay, DayOfWeek.Monday);

            // 比较两个日期的年份和周数
            return year1 == year2 && week1 == week2;
        }

        // 示例：判断 curLocalTime 和 anotherTime 是否是同一天
        public bool IsSameDay(DateTime time1, DateTime time2)
        {
            return time1.Date == time2.Date;
        }

        public int GetTimeDifferenceInMinutes(string range)
        {
            // 拆分开始时间和结束时间
            string[] parts = range.Split('-');
            if (parts.Length != 2)
                throw new ArgumentException("格式错误，应为 \"hh:mm-hh:mm\"");

            string startTimeStr = parts[0].Trim();
            string endTimeStr = parts[1].Trim();

            // 解析时间
            if (!TimeSpan.TryParse(startTimeStr, out TimeSpan startTime))
                throw new ArgumentException($"无法解析开始时间：{startTimeStr}");

            if (!TimeSpan.TryParse(endTimeStr, out TimeSpan endTime))
                throw new ArgumentException($"无法解析结束时间：{endTimeStr}");

            // 如果结束时间小于开始时间，则视为跨天
            if (endTime < startTime)
            {
                endTime = endTime.Add(TimeSpan.FromDays(1));
            }

            // 计算时间差并返回分钟数
            int resluet = (int)(endTime - startTime).TotalMinutes;
            // resluet = resluet > 0 ? resluet : 1;
            return resluet;
        }

        // 可用字符集
        private static readonly string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        private Random _random = new Random();
        private static HashSet<string> _generatedCodes = new HashSet<string>();
        // 生成指定长度且同时包含字母和数字的唯一编码
        public string GenerateName(int length)
        {
            string name;
            do
            {
                name = GenerateRandomCode(length);
            } while (_generatedCodes.Contains(name) || !ContainsBothLettersAndNumbers(name));

            _generatedCodes.Add(name);
            return name;
        }

        // 生成一个随机编码
        private string GenerateRandomCode(int length)
        {
            char[] result = new char[length];
            for (int i = 0; i < length; i++)
            {
                result[i] = _chars[_random.Next(_chars.Length)];
            }
            return new string(result);
        }

        // 检查字符串是否同时包含字母和数字
        private bool ContainsBothLettersAndNumbers(string str)
        {
            bool hasLetter = false, hasNumber = false;
            foreach (char c in str)
            {
                if (char.IsLetter(c)) hasLetter = true;
                if (char.IsDigit(c)) hasNumber = true;
                if (hasLetter && hasNumber) return true;
            }
            return false;
        }

        public void addGameExp(addPointType type, decimal count = 0)
        {
            long curTime = GameHelper.GetNowTime();

            int points = 0;
            if (type == addPointType.eliminate)
            {
                points = ConfigSystem.GetConfig<CommonModel>().eliminatePoints;
            }
            else if (type == addPointType.ads)
            {
                points = getAdsAddPoint();

            }
            else if (type == addPointType.buy)
            {
                int a = ConfigSystem.GetConfig<CommonModel>().USDPoints;
                points = (int)Math.Ceiling(ConfigSystem.GetConfig<CommonModel>().USDPoints * (float)count);
            }

            addPointsData data = new addPointsData();
            data.points = points;
            data.type = type;
            SaveData.GetRankData().selfUser.addPointsDic.TryAdd(curTime, data);

            addPoints += points;
            addPointsUI += points;


            if (addPoints > 0)
            {
                GameDispatcher.Instance.Dispatch(GameMsg.add_points);
            }

            upSelfPoints();
        }

        public int getAddPoints()
        {
            int temp = addPoints;
            addPoints = 0;
            return temp;
        }

        public int getAddPointsUI()
        {
            int temp = addPointsUI;
            addPointsUI = 0;
            return temp;
        }

        // 广告积分是否达上限
        public int getAdsAddPoint()
        {
            long curTime = GameHelper.GetNowTime();
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(curTime);
            DateTime curLocalTime = utcTime.ToLocalTime();
            int points = 0;
            foreach (KeyValuePair<long, addPointsData> kvp in SaveData.GetRankData().selfUser.addPointsDic)
            {
                long time = kvp.Key;
                addPointsData data = kvp.Value;
                DateTime utcTime_history = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(time);
                DateTime curLocalTime_history = utcTime_history.ToLocalTime();
                bool sameDay = IsSameDay(curLocalTime, curLocalTime_history);
                if (sameDay)
                {
                    if (data.type == addPointType.ads)
                    {
                        points += data.points;
                    }
                }
            }
            int nextPoints = ConfigSystem.GetConfig<CommonModel>().adsPoints[0] + points;
            int maxPoints = ConfigSystem.GetConfig<CommonModel>().adsPoints[1];
            int minPoints = ConfigSystem.GetConfig<CommonModel>().adsPoints[0];
            if (ConfigSystem.GetConfig<CommonModel>().adsPoints[1] < 0)
            {
                return ConfigSystem.GetConfig<CommonModel>().adsPoints[0];
            }

            if (nextPoints >= ConfigSystem.GetConfig<CommonModel>().adsPoints[1])
            {
                if (maxPoints - points < 0)
                {
                    return 0;
                }

                return maxPoints - points;
            }

            return ConfigSystem.GetConfig<CommonModel>().adsPoints[0];
        }

        // 更新自己的积分
        public void upSelfPoints()
        {
            List<long> keysToRemove = new List<long>();
            long curTime = GameHelper.GetNowTime();
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(curTime);
            DateTime curLocalTime = utcTime.ToLocalTime();
            DayOfWeek dayOfWeek = curLocalTime.DayOfWeek;
            int hour = curLocalTime.Hour;
            SaveData.GetRankData().selfUser.weekPoints = 0;
            SaveData.GetRankData().selfUser.dayPoints = 0;
            SaveData.GetRankData().selfUser.hourPoints = 0;

            foreach (KeyValuePair<long, addPointsData> kvp in SaveData.GetRankData().selfUser.addPointsDic)
            {
                long time = kvp.Key;
                addPointsData data = kvp.Value;
                DateTime utcTime_history = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(time);
                DateTime curLocalTime_history = utcTime_history.ToLocalTime();
                DayOfWeek dayOfWeek_history = curLocalTime_history.DayOfWeek;
                int hour_history = curLocalTime_history.Hour;
                bool sameWeek = isInSameWeek(curLocalTime, curLocalTime_history);
                if (sameWeek)
                {
                    SaveData.GetRankData().selfUser.weekPoints += data.points;
                    if (dayOfWeek == dayOfWeek_history)
                    {
                        SaveData.GetRankData().selfUser.dayPoints += data.points;
                        int round = hour / (hourTime / 60);
                        int last_round = hour_history / (hourTime / 60);
                        if (round == last_round)
                        {
                            SaveData.GetRankData().selfUser.hourPoints += data.points;
                        }
                    }
                }
                else
                {
                    keysToRemove.Add(kvp.Key);
                }
            }

            // 遍历完成后删除所有标记为删除的键值对
            foreach (var key in keysToRemove)
            {
                SaveData.GetRankData().selfUser.addPointsDic.Remove(key);
            }
        }

        // 获取某个时间点之后的指定星期几的具体时间（如：下周日 23:59:59）
        public DateTime GetThisWeekdayTime(DateTime fromTime, DayOfWeek targetDay, int hour, int minute, int second)
        {
            int daysToAdd = ((int)targetDay - (int)fromTime.DayOfWeek + 7) % 7;
            if (daysToAdd == 0)
            {
                // 如果今天就是目标星期几，则判断时间是否已经过了设定的时间
                TimeSpan targetTimeSpan = new TimeSpan(hour, minute, second);
                if (fromTime.TimeOfDay > targetTimeSpan)
                {
                    daysToAdd = 7; // 已过当天设定时间，取下周的
                }
            }

            return fromTime.Date
                    .AddDays(daysToAdd)
                    .AddHours(hour)
                    .AddMinutes(minute)
                    .AddSeconds(second);
        }

        // 获取周日日期
        public string getLastLoginWeekEndTime()
        {
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(SaveData.GetSaveObject().lastLoginTime);
            DateTime curLocalTime = utcTime.ToLocalTime();

            int daysToAdd = ((int)DayOfWeek.Sunday - (int)curLocalTime.DayOfWeek + 7) % 7;
            // if (daysToAdd == 0 && curLocalTime.Hour >= 0)
            // {
            //     // 如果已经过了今天的时间点，就取下一周的
            //     daysToAdd = 7;
            // }

            DateTime thisWeekend = curLocalTime.Date.AddDays(daysToAdd);
            string weekendDateStr = thisWeekend.ToString("yyyy-MM-dd");

            return weekendDateStr;
        }

        // 获取lastLoginTime日期
        public string getLastLoginDateTime()
        {
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(SaveData.GetSaveObject().lastLoginTime);
            DateTime curLocalTime = utcTime.ToLocalTime();
            string dateStr = curLocalTime.ToString("yyyy-MM-dd");
            return dateStr;
        }

        // 获取lastLoginTime当前轮日期
        public string getLastLoginRoundTime()
        {
            DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(SaveData.GetSaveObject().lastLoginTime);
            DateTime curLocalTime = utcTime.ToLocalTime();
            int hour = curLocalTime.Hour;
            int round = hour / ConfigSystem.GetConfig<CommonModel>().HourTime;

            string dateStr = curLocalTime.ToString("yyyy-MM-dd ");
            int endHour = (round + 1) * ConfigSystem.GetConfig<CommonModel>().HourTime;
            string endHM = $"{endHour:D2}:00:00";
            if (endHour >= 24)
            {
                endHM = "00:00:00";
            }

            return dateStr + endHM;
        }

        // 删除大于30天的数据
        private void remove30DaysData()
        {
            int count = SaveData.GetRankData().rankRewardData.Count;
            for (int i = count - 1; i >= 0; i--)
            {
                RankRewardData data = SaveData.GetRankData().rankRewardData[i];
                if (data.type == rankType.week || data.type == rankType.day)
                {
                    if (IsMoreThan30Days(data.time))
                    {
                        SaveData.GetRankData().rankRewardData.RemoveAt(i);
                    }
                }
                else if (data.type == rankType.hour)
                {
                    if (IsOver30Days(data.time))
                    {
                        SaveData.GetRankData().rankRewardData.RemoveAt(i);
                    }
                }
            }
        }

        public bool IsMoreThan30Days(string dateStr)
        {
            DateTime specifiedDate = DateTime.ParseExact(dateStr, "yyyy-MM-dd", null);
            DateTime currentDate = DateTime.Today;
            int daysDifference = (currentDate - specifiedDate).Days;
            return daysDifference > 30;
        }

        public static bool IsOver30Days(string dateTimeStr)
        {
            DateTime specifiedDateTime;
            if (!DateTime.TryParseExact(dateTimeStr, "yyyy-MM-dd HH:mm:ss", null,
                                        DateTimeStyles.None, out specifiedDateTime))
            {
                throw new ArgumentException("日期格式无效");
            }

            TimeSpan diff = DateTime.Now - specifiedDateTime;
            return diff.TotalDays > 30;
        }
    }

}
