using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using GameDAL.FriendRoom;
using MrWu.Debug;
using Newtonsoft.Json;

namespace Server
{
    // 配置倍率 平衡区间 比如 20 倍的 平衡参数 7500
    //                      2 倍 平衡参数 1000
    //   

    // 根据倍率 配置那些人需要平衡
    public partial class LuckPlayerManager
    {
        private BalanceData _balanceData = new BalanceData();

        /// <summary>
        /// 所有的平衡配置
        /// </summary>
        private List<BalanceRange> BalanceAllConfigs => _balanceData.BalanceRanges;

        private Dictionary<float, BalanceRange> BalanceRangesDic = new Dictionary<float, BalanceRange>();

        /// <summary>
        /// 初始化，添加，删除 才需修改
        /// </summary>
        private Dictionary<float, BalanceRoomRateRule> RulesDic = new Dictionary<float, BalanceRoomRateRule>();

        private const string BalanceDataPath = "LuckRecord/ClubBalanceData.txt";

        public float GetBalanceRangeId(float beilv, int fightCnt)
        {
            return fightCnt * 10000 + beilv;
        }

        /// <summary>
        /// 获取所有的配置
        /// </summary>
        /// <returns></returns>
        public IEnumerable<BalanceRange> GetAllBalanceRange()
        {
            return BalanceAllConfigs;
        }

        /// <summary>
        /// 添加平衡区间
        /// </summary>
        /// <param name="beilv">倍率</param>
        /// <param name="fightCnt">总局数</param>
        /// <param name="balanceValue">平衡值</param>
        /// <returns></returns>
        public bool AddBalanceRange(float beilv, int fightCnt, int balanceValue)
        {
            BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
            if (balanceRange == null)
            {
                balanceRange = new BalanceRange()
                {
                    BeiLv = beilv,
                    MaxFightCnt = fightCnt,
                    BalanceValue = balanceValue
                };
                BalanceAllConfigs.Add(balanceRange);

                //添加所有玩家
                for (int i = 0; i < _balanceData.UserIds.Count; i++)
                {
                    AddBalancePlayer(balanceRange, _balanceData.UserIds[i]);
                }

                return true;
            }

            return false;
        }

        public bool SetBalanceRange(float beilv, int fightCnt, int balanceValue)
        {
            if (balanceValue < 1000)
            {
                Debug.Error("平衡参数过低!");
                return false;
            }

            BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
            if (balanceRange != null)
            {
                balanceRange.BalanceValue = balanceValue;
                return true;
            }

            return false;
        }

        /// <summary>
        /// 移除平衡区间
        /// </summary>
        /// <param name="beilv"></param>
        /// <param name="fightCnt"></param>
        /// <returns></returns>
        public bool RemoveBalanceRange(float beilv, int fightCnt)
        {
            BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
            if (balanceRange == null)
            {
                return false;
            }

            BalanceRangesDic.Remove(balanceRange.Id);
            BalanceAllConfigs.Remove(balanceRange);
            return true;
        }

        public BalanceRange GetBalanceRange(float id)
        {
            if (!BalanceRangesDic.TryGetValue(id, out BalanceRange balanceRange))
            {
                for (int i = 0; i < BalanceAllConfigs.Count; i++)
                {
                    if (Math.Abs(BalanceAllConfigs[i].Id - id) < 0.001f)
                    {
                        balanceRange = BalanceAllConfigs[i];
                        BalanceRangesDic[id] = balanceRange;
                    }
                }
            }

            return balanceRange;
        }

        public BalanceRange GetBalanceRange(float beiLv, int fightCnt)
        {
            return GetBalanceRange(GetBalanceRangeId(beiLv, fightCnt));
        }

        public bool AddRoomRateRule(float beiLv, int fightCnt, int modeType)
        {
            BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
            if (rule != null)
            {
                return false;
            }

            rule = new BalanceRoomRateRule()
            {
                ModeType = modeType,
                BeiLv = beiLv,
                FightCnt = fightCnt
            };

            RulesDic[GetBalanceRangeId(beiLv, fightCnt)] = rule;
            _balanceData.Rules.Add(rule);

            return true;
        }

        public bool RemoveRoomRateRule(float beiLv, int fightCnt)
        {
            BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
            if (rule == null)
            {
                return false;
            }

            bool result = _balanceData.Rules.Remove(rule);

            if (result && !RulesDic.Remove(GetBalanceRangeId(beiLv, fightCnt)))
            {
                Debug.Error("未能删除规则");
                return false;
            }

            return result;
        }

        public bool AddRoomRateRuleItem(float beiLv, int fightCnt, int minScore, int maxScore, int roomRate)
        {
            BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
            if (rule == null)
            {
                return false;
            }

            if (maxScore <= minScore || roomRate <= 0)
            {
                return false;
            }

            for (int i = 0; i < rule.Ranges.Count; i++)
            {
                if (maxScore <= rule.Ranges[i].MinScore || minScore > rule.Ranges[i].MaxScore)
                {
                    continue;
                }

                Debug.Error("区间有交叉!");
                return false;
            }

            rule.Ranges.Add(new BalanceRoomRange()
            {
                MinScore = minScore,
                MaxScore = maxScore,
                Rate = roomRate
            });

            return true;
        }

        public bool RemoveRoomRateRuleItem(float beiLv, int fightCnt, int minScore, int maxScore, int roomRate)
        {
            BalanceRoomRateRule rule = GetRoomRateRule(beiLv, fightCnt);
            if (rule == null)
            {
                return false;
            }

            for (int i = 0; i < rule.Ranges.Count; i++)
            {
                if (rule.Ranges[i].MinScore == minScore && rule.Ranges[i].MaxScore == maxScore &&
                    roomRate == rule.Ranges[i].Rate)
                {
                    rule.Ranges.RemoveAt(i);
                    return true;
                }
            }

            return false;
        }

        public BalanceRoomRateRule GetRoomRateRule(float beiLv, int fightCnt)
        {
            if (RulesDic.TryGetValue(GetBalanceRangeId(beiLv, fightCnt), out BalanceRoomRateRule roomRateRule))
            {
                return roomRateRule;
            }

            return null;
        }

        public List<Tuple<BalanceRange, BalancePlayer>> GetBalancePlayers(int userid)
        {
            List<Tuple<BalanceRange, BalancePlayer>> balancePlayers = new List<Tuple<BalanceRange, BalancePlayer>>();

            for (int i = 0; i < BalanceAllConfigs.Count; i++)
            {
                BalancePlayer player = GetBalancePlayer(BalanceAllConfigs[i], userid);
                if (player == null)
                {
                    break;
                }

                balancePlayers.Add(new Tuple<BalanceRange, BalancePlayer>(BalanceAllConfigs[i], player));
            }

            return balancePlayers;
        }

        public BalancePlayer GetBalancePlayer(BalanceRange balanceRange, int userid)
        {
            if (balanceRange.BalancePlayersDic.TryGetValue(userid, out BalancePlayer player))
            {
                return player;
            }

            return null;
        }

        public bool AddBalancePlayer(int userid)
        {
            if (ExistsPlayer(userid))
            {
                return false;
            }

            _balanceData.UserIds.Add(userid);

            //为每个玩法都添加上
            for (int i = 0; i < BalanceAllConfigs.Count; i++)
            {
                AddBalancePlayer(BalanceAllConfigs[i], userid);
            }

            return true;
        }

        public bool RemoveBalancePlayer(int userid)
        {
            if (_balanceData.UserIds.Remove(userid))
            {
                for (int i = 0; i < BalanceAllConfigs.Count; i++)
                {
                    RemoveBalancePlayer(BalanceAllConfigs[i], userid);
                }

                return true;
            }

            return false;
        }

        private void AddBalancePlayer(BalanceRange balanceRange, int userid)
        {
            balanceRange.BalancePlayersDic.TryAdd(userid, new BalancePlayer()
            {
                UserId = userid
            });
        }

        private void RemoveBalancePlayer(BalanceRange balanceRange, int userid)
        {
            if (balanceRange.BalancePlayersDic.TryRemove(userid, out BalancePlayer _balance))
            {
                Debug.Info($"移除用户:{_balance.Score}");
            }
        }

        public bool ExistsPlayer(int userid)
        {
            for (int i = 0; i < _balanceData.UserIds.Count; i++)
            {
                if (_balanceData.UserIds[i] == userid)
                {
                    return true;
                }
            }

            return false;
        }


        public List<string> FindBalancePlayer(int userid)
        {
            List<string> logs = new List<string>();
            for (int i = 0; i < BalanceAllConfigs.Count; i++)
            {
                BalancePlayer banBalancePlayer = GetBalancePlayer(BalanceAllConfigs[i], userid);
                if (banBalancePlayer == null)
                {
                    continue;
                }

                logs.Add(
                    $"倍率:{BalanceAllConfigs[i].BeiLv} 总局数:{BalanceAllConfigs[i].MaxFightCnt} {banBalancePlayer.ToString()}");
            }

            return logs;
        }

        /// <summary>
        /// 加载俱乐部平衡数据
        /// </summary>
        private void LoadClubBalanceData()
        {
            if (!File.Exists(BalanceDataPath))
            {
                return;
            }

            string jsondata = File.ReadAllText(BalanceDataPath);
            _balanceData = JsonConvert.DeserializeObject<BalanceData>(jsondata);

            for (int i = 0; i < BalanceAllConfigs.Count; i++)
            {
                foreach (var balancePlayer in BalanceAllConfigs[i].BalancePlayers)
                {
                    BalanceAllConfigs[i].BalancePlayersDic[balancePlayer.UserId] = balancePlayer;
                }
            }

            if (_balanceData.Rules != null)
            {
                for (int i = 0; i < _balanceData.Rules.Count; i++)
                {
                    RulesDic[_balanceData.Rules[i].Id] = _balanceData.Rules[i];
                }
            }
        }

        private void SaveClubBalanceData()
        {
            if (BalanceAllConfigs.Count <= 0)
            {
                return;
            }

            FileInfo fileInfo = new FileInfo(BalanceDataPath);
            if (!fileInfo.Directory.Exists)
            {
                fileInfo.Directory.Create();
            }

            for (int i = 0; i < BalanceAllConfigs.Count; i++)
            {
                BalanceAllConfigs[i].BalancePlayers.Clear();
                BalanceAllConfigs[i].BalancePlayers.AddRange(BalanceAllConfigs[i].BalancePlayersDic.Values);
            }

            File.WriteAllText(BalanceDataPath, JsonConvert.SerializeObject(_balanceData));
        }

        public bool SetSessionFightScore(float beilv, int fightCnt, int userid, int score)
        {
            BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
            if (balanceRange == null)
            {
                return false;
            }

            BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
            if (balancePlayer == null)
            {
                return false;
            }

            balancePlayer.Score += score;
            return true;
        }

        /// <summary>
        /// 添加一场战斗的分
        /// </summary>
        /// <param name="beilv"></param>
        /// <param name="userid"></param>
        /// <param name="score"></param>
        /// <param name="isBigWinner">是否是大赢家</param>
        public void AddSessionFightScore(float beilv, int fightCnt, int userid, int score, bool isBigWinner)
        {
            BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
            if (balanceRange == null)
            {
                return;
            }

            BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
            if (balancePlayer == null)
            {
                return;
            }

            Debug.Info($"AddSessionFightScore: {userid} {score}");

            //先得到规则
            BalanceRoomRateRule rule = GetRoomRateRule(beilv, fightCnt);
            if (rule != null) //处理房费
            {
                //得到区间
                BalanceRoomRange range = null;
                for (int i = 0; i < rule.Ranges.Count; i++)
                {
                    if (score > rule.Ranges[i].MinScore && score <= rule.Ranges[i].MaxScore)
                    {
                        range = rule.Ranges[i];
                        break;
                    }
                }

                if (range != null)
                {
                    if (rule.ModeType == 1 || (rule.ModeType == 2 && isBigWinner))
                    {
                        score -= range.Rate;
                        balancePlayer.RoomRate += range.Rate;
                        Debug.Info($"扣除房费:{balancePlayer.RoomRate}");
                    }
                }
            }

            balancePlayer.Score += score;
            balancePlayer.TempScore = 0;
        }

        /// <summary>
        /// 添加一局战斗的分 子
        /// </summary>
        /// <param name="beilv"></param>
        /// <param name="userid"></param>
        /// <param name="score"></param>
        public void AddOnceFightScore(float beilv, int fightCnt, int userid, int score)
        {
            BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
            if (balanceRange == null)
            {
                Debug.Info($"没找到玩法! {beilv} {fightCnt}");
                return;
            }

            BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
            if (balancePlayer == null)
            {
                Debug.Info($"没找到玩法 玩家：{userid}!");
                return;
            }

            Debug.Info($"AddOnceFightScore : {userid} {(score * beilv)}");
            balancePlayer.TempScore += (int)(score * beilv);
        }

        /// <summary>
        /// 获取平衡数据
        /// </summary>
        /// <param name="beilv"></param>
        /// <param name="userid"></param>
        /// <returns></returns>
        public ClubPlayerBalanceType GetBalancePlayerType(float beilv, int fightCnt, int userid)
        {
            BalanceRange balanceRange = GetBalanceRange(beilv, fightCnt);
            if (balanceRange == null)
            {
                return ClubPlayerBalanceType.None;
            }

            BalancePlayer balancePlayer = GetBalancePlayer(balanceRange, userid);
            if (balancePlayer == null)
            {
                return ClubPlayerBalanceType.None;
            }

            int score = balancePlayer.TempScore + balancePlayer.Score;

            int diffValue = Math.Abs(score) - balanceRange.BalanceValue;
            if (diffValue <= 0)
            {
                Debug.Info($"已经是平衡状态! {userid}");
                return ClubPlayerBalanceType.Normal;
            }

            float rate = (diffValue / (float)balanceRange.BalanceValue) * 0.5f;
            if (score < 0) //输了就加大发牌概率
            {
                rate *= 2f;
            }

            Debug.Info($"计算概率:{userid} {diffValue} {balancePlayer.Score} {rate}");

            Random random = GetRandom();
            bool isBalance = random.NextDouble() < rate;
            ReleaseRandom(random);
            if (isBalance)
            {
                return score > 0 ? ClubPlayerBalanceType.BadLuck : ClubPlayerBalanceType.Luck;
            }

            return ClubPlayerBalanceType.Normal;
        }

        public class BalanceData
        {
            /// <summary>
            /// 房费规则
            /// </summary>
            public List<BalanceRoomRateRule> Rules = new List<BalanceRoomRateRule>();

            /// <summary>
            /// 玩法配置
            /// </summary>
            public List<BalanceRange> BalanceRanges = new List<BalanceRange>();

            /// <summary>
            /// 所有玩家
            /// </summary>
            public List<int> UserIds = new List<int>();
        }

        /// <summary>
        /// 房费规则
        /// </summary>
        public class BalanceRoomRateRule
        {
            /// <summary>
            /// 这个用来做ID
            /// </summary>
            [JsonIgnore]
            public float Id
            {
                get { return FightCnt * 10000 + BeiLv; }
            }

            /// <summary>
            /// 模式类型  1 所有人出  2 大赢家出
            /// </summary>
            public int ModeType;

            /// <summary>
            /// 房费
            /// </summary>
            public float BeiLv;

            /// <summary>
            /// 总局数
            /// </summary>
            public int FightCnt;

            /// <summary>
            /// 区间
            /// </summary>
            public List<BalanceRoomRange> Ranges = new List<BalanceRoomRange>();
        }

        /// <summary>
        /// 房费区间
        /// </summary>
        public class BalanceRoomRange
        {
            /// <summary>
            /// 最小值
            /// </summary>
            public int MinScore;

            /// <summary>
            /// 最大值
            /// </summary>
            public int MaxScore;

            /// <summary>
            /// 房费
            /// </summary>
            public int Rate;
        }

        /// <summary>
        /// 平衡区间
        /// </summary>
        public class BalanceRange
        {
            /// <summary>
            /// 这个用来做ID
            /// </summary>
            [JsonIgnore]
            public float Id
            {
                get { return MaxFightCnt * 10000 + BeiLv; }
            }

            /// <summary>
            /// 倍率
            /// </summary>
            public float BeiLv;

            /// <summary>
            /// 总局数
            /// </summary>
            public int MaxFightCnt;

            /// <summary>
            /// 平衡值
            /// </summary>
            public int BalanceValue;

            /// <summary>
            /// 平衡玩家的数据
            /// </summary>
            public List<BalancePlayer> BalancePlayers = new List<BalancePlayer>();

            [JsonIgnore]
            public ConcurrentDictionary<int, BalancePlayer> BalancePlayersDic =
                new ConcurrentDictionary<int, BalancePlayer>();
        }

        /// <summary>
        /// 平衡玩家数据
        /// </summary>
        public class BalancePlayer
        {
            /// <summary>
            /// 玩家ID
            /// </summary>
            public int UserId;

            /// <summary>
            /// 当前分值
            /// </summary>
            public int Score;

            /// <summary>
            /// 临时计算用，这个是小局分
            /// </summary>
            public int TempScore;

            /// <summary>
            /// 房费
            /// </summary>
            public int RoomRate;

            public override string ToString()
            {
                return $"Userid:{UserId},Score:{Score},RoomRate:{RoomRate}";
            }
        }

        public enum ClubPlayerBalanceType
        {
            /// <summary>
            /// 不参与平衡
            /// </summary>
            None = 0,

            /// <summary>
            /// 正常
            /// </summary>
            Normal = 1,

            /// <summary>
            /// 幸运
            /// </summary>
            Luck = 2,

            /// <summary>
            /// 不幸运
            /// </summary>
            BadLuck = 3,
        }
    }
}