using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using GameData;
using GameData.Club;
using GameMessage;
using MrWu.Debug;
using ObjectModel.Club;
using Server.DB.Sql;

namespace GameDAL.Club
{
    public static class ClubDBUtil
    {
        /// <summary>
        /// id增量
        /// </summary>
        public const int IdIncrement = 100000;
        
        #region ClubExitMatchClubList

        /// <summary>
        /// 移除淘汰（退赛俱乐部）
        /// 直接添加解禁标记 （ReliefId），不直接删除
        /// </summary>
        public static async Task RemoveClubExitMatchAsync(int leagueClubId, int clubId)
        {
            long timeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            string sql = "UPDATE ClubExitMatchClubList SET ReliefId=@ReliefId where ClubId=@ClubId AND LeagueClubId=@LeagueClubId AND ReliefId=0";
            await GameDB.Instance.DapperExecuteAsync(dbbase.game2018, sql,
                new { 
                    ClubId = clubId, 
                    LeagueClubId = leagueClubId, 
                    ReliefId = timeStamp
                });
        }
        
        /// <summary>
        /// 添加淘汰（退赛俱乐部）
        /// </summary>
        public static async Task AddClubExitMatchAsync(LeagueMatchClubExitScore data)
        {
            const string sql = @"
                INSERT INTO ClubExitMatchClubList (
                    [ClubId],
                    [LeagueClubId],
                    [MatchId],
                    [CardScore],
                    [DeskScore],
                    [ClubUserSumScore],
                    [LeagueScore],
                    [JoinRoom],
                    [UpdateTime],
                    [ReliefId],
                    [AwardId]
                ) VALUES (
                    @ClubId,
                    @LeagueClubId,
                    @MatchId,
                    @CardScore,
                    @DeskScore,
                    @ClubUserSumScore,
                    @LeagueScore,
                    @JoinRoom,
                    @UpdateTime,
                    @ReliefId,
                    @AwardId
                )";
            await GameDB.Instance.DapperExecuteAsync(dbbase.game2018, sql, data);
        }

        public static async Task UpdateAwardIdOnMatchClose(int matchId)
        {
            string sql =
                $"UPDATE ClubExitMatchClubList SET AwardId = {ConstData.AwardId_InHistoryCloseMatchWithResetScore} where MatchId=@MatchId AND ReliefId <> 0";
            await GameDB.Instance.DapperExecuteAsync(dbbase.game2018, sql, new { MatchId = matchId });
        }

        /// <summary>
        /// 获取联盟下退赛俱乐部的列表
        /// </summary>
        public static List<LeagueMatchClubExitScore> GetLeagueExitMathClubList(int leagueClubId)
        {
            // ReliefId = 0 表示当前没有解禁的俱乐部数据
            string sql = "SELECT * FROM ClubExitMatchClubList where LeagueClubId=@LeagueClubId AND ReliefId=0";
            var list = GameDB.Instance.DapperQuery<LeagueMatchClubExitScore>(dbbase.game2018, sql, new { LeagueClubId = leagueClubId });
            return list?.ToList() ?? new List<LeagueMatchClubExitScore>();
        }
        
        /// <summary>
        /// 获取联盟下已经解禁但是没有产生颁奖记录的俱乐部数据
        /// </summary>
        /// <param name="leagueClubId">联盟俱乐部Id</param>
        /// <param name="startTime">比赛开始时间</param>
        /// <param name="endTime">比赛结束时间</param>
        /// <param name="isHistoryMatch">是否是历史比赛</param>
        public static async Task<List<LeagueMatchClubExitScore>> GetLeagueExitClubReliefDataAsync(int leagueClubId, int leagueMatchId,
            DateTime startTime, DateTime endTime, bool isHistoryMatch)
        {
            var parameters = new DynamicParameters();
            string sql = "SELECT * FROM ClubExitMatchClubList where LeagueClubId=@LeagueClubId";
            parameters.Add("LeagueClubId", leagueClubId);
            parameters.Add("MatchId", leagueMatchId);
            parameters.Add("StartTime", new DateTimeOffset(startTime).ToUnixTimeSeconds());
            parameters.Add("EndTime", new DateTimeOffset(endTime).ToUnixTimeSeconds());

            sql += isHistoryMatch
                ? $" AND MatchId=@MatchId AND ReliefId>=@StartTime AND ReliefId<=@EndTime AND AwardId < {ConstData.AwardId_Default} AND AwardId > 0"
                : $" AND AwardId = {ConstData.AwardId_Default}";
            
            var list = await GameDB.Instance.DapperQueryAsync<LeagueMatchClubExitScore>(dbbase.game2018, sql, 
                parameters);
            return list?.ToList() ?? new List<LeagueMatchClubExitScore>();
        }
        
        /// <summary>
        /// 获取联盟下已经解禁的颁奖记录历史数据
        /// </summary>
        public static async Task<List<LeagueMatchClubExitScore>> GetLeagueAwardExitClubReliefRecord(int leagueClubId, int leagueMatchId, List<long> awardIds)
        {
            string sql = "SELECT * FROM ClubExitMatchClubList where LeagueClubId=@LeagueClubId AND AwardId In @AwardIds";
            var list = await GameDB.Instance.DapperQueryAsync<LeagueMatchClubExitScore>(dbbase.game2018, sql, 
                new { LeagueClubId = leagueClubId, MatchId = leagueMatchId, AwardIds = awardIds });
            return list?.ToList() ?? new List<LeagueMatchClubExitScore>();
        }

        /// <summary>
        /// 直接数据库的联盟颁奖逻辑，并对解禁数据进行标记
        /// </summary>
        public static async Task<bool> DoLeagueAwardRecord(long awardId, int leagueClubId, int leagueMatchId, List<AwardRecord> list)
        {
            if (list == null || list.Count < 1) return false;
            
            string awardSql = @"
                INSERT INTO LeagueAwardRecord([RecordId],[CreateTime],[ClubMatchId],[ClubName],[ClubId],
[CardScore],[DeskScore],[ClubUserSumScore],[JoinRoom],[LeagueScore],[Index]) Values 
(@RecordId,@CreateTime,@ClubMatchId,@ClubName,@ClubId,@CardScore,@DeskScore,@ClubUserSumScore,@JoinRoom,@LeagueScore,@Index)";
            // 记录颁奖数据 （如果为1就表示已经颁奖过，但是不会在颁奖记录中汇总）
            string exitReliefSql = @$"UPDATE ClubExitMatchClubList 
SET AwardId = CASE 
    WHEN (ReliefId <> 0 AND AwardId = {ConstData.AwardId_Default}) THEN @AwardId
    ELSE {ConstData.AwardId_AwardNoInHistory}
    END
WHERE LeagueClubId = @LeagueClubId 
  AND MatchId = @MatchId";
            
            Debug.Log(exitReliefSql);

            return await GameDB.Instance.DapperExecuteTransactionAsync(dbbase.game2018, async (conn, tran) =>
            {
                await conn.ExecuteAsync(awardSql, list, tran);
                await conn.ExecuteAsync(exitReliefSql, new
                {
                    AwardId = awardId,
                    LeagueClubId = leagueClubId, 
                    MatchId = leagueMatchId
                }, tran);

                return true;
            });
        }

        #endregion

        #region clubPayCard
        
        /// <summary>
        /// 带日志的添加房卡操作 （目前只处理添加的情况）
        /// </summary>
        public static async Task<bool> AddClubPayCardAsync(List<ClubPayCardDBEntity> entities)
        {
            if(entities == null || entities.Count <= 0) return false;
            int clubId = entities[0].clubId;
            int cardCount = 0;
            foreach (var e in entities)
            {
                if (clubId != e.clubId)
                {
                    Debug.Warning("[Club]批处理暂时只处理一个俱乐部的数据。");
                    return false;
                }
                cardCount += e.cardCount;
            }

            if (cardCount <= 0)
            {
                Debug.Warning("[Club]添加的房卡数量小于0!暂不处理减逻辑");
                return false;
            }
            
            const string logSql = @"
                INSERT INTO clubPayCard ([clubId],[userId],[cardCount],[nickName],[datetime],[sex],[origin]
                ) VALUES (@clubId,@userId,@cardCount,@nickName,@datetime,@sex,@origin)";
            const string clubUpdateSql = @"
                UPDATE top(1) clubs SET [cards] = [cards] + @cardCount
                WHERE [id] = @clubId";
            clubId = clubId - IdIncrement;
            await GameDB.Instance.DapperExecuteAsync(dbbase.game2018, clubUpdateSql, new { clubId, cardCount });
            await GameDB.Instance.DapperExecuteAsync(dbbase.gamedb, logSql, entities);
            return true;
        }
        

        /// <summary>
        /// 分页获取俱乐部的房卡记录
        /// </summary>
        public static async Task<(int Count, List<ClubPayCardDBEntity> Data)> GetClubPayCardAsync(int clubId,  int pageNumber, int pageSize)
        {
            int skip = pageSize * (pageNumber - 1);
            // 分页获取
            string sql = @"
WITH Results As (SELECT *, ROW_NUMBER() OVER (ORDER BY id DESC) AS RowNum FROM clubPayCard WHERE clubId=@clubId)
SELECT * FROM Results WHERE RowNum BETWEEN @StartIndex AND @EndIndex;
SELECT COUNT(*) FROM clubPayCard WHERE clubId=@clubId;
";
            return await GameDB.Instance.DapperQueryMultipleAsync(dbbase.gamedb, sql, 
                new { clubId, StartIndex = skip, EndIndex = skip + pageSize }, 
                async reader =>
            {
                var datas = (await reader.ReadAsync<ClubPayCardDBEntity>()).ToList();
                var count = await reader.ReadSingleAsync<int>();
                return (count, datas);
            });
        }
        #endregion

        #region clubs_rm
        public static async Task<List<int>> GetRemoveClubIds()
        {
            string sql = "SELECT Id FROM ClubsRM";
            var list = await GameDB.Instance.DapperQueryAsync<DBEntitys.ClubRM>(dbbase.game2018, sql, null);
            return list?.Select(x => x.Id).ToList() ?? new List<int>();
        }
        

        public static async Task<bool> DeleteClubAsync(DBEntitys.ClubRM club, List<DBEntitys.ClubPlayerDBEntity> clubPlayers)
        {
            string clubsSql = "DELETE FROM clubs WHERE ID = @Id";
            string clubsRmSql =  @"
                INSERT INTO ClubsRM (
                    [Id],[ClubName],[Notice],[Cards],[ManCnt],[Mans],[Newways],[WayVer],[Password],[CreateTime],[DeleteTime],[LeaderUserId], [Setting]
                ) VALUES (
                     @Id,@ClubName,@Notice,@Cards,@ManCnt,@Mans,@Newways,@WayVer,@Password,@CreateTime,@DeleteTime,@LeaderUserId,@Setting
                )";
            string leaguePowerSql = $"DELETE FROM LeagueClubLeaguePower WHERE ClubId = @Id + {IdIncrement}";
            string playerUpdateSql = "UPDATE TOP(1) players SET myclubinfodata=@myclubinfodata, joinclubinfodata=@joinclubinfodata WHERE userid2018 = @userid2018";
            string clubmsgRmSql = "DELETE FROM clubmsg WHERE receiveid = @Id";

            return await GameDB.Instance.DapperExecuteTransactionAsync(dbbase.game2018, async (conn, tran) =>
            {
                await conn.ExecuteAsync(clubsRmSql, club, tran);
                await conn.ExecuteAsync(clubsSql, club, tran);
                await conn.ExecuteAsync(leaguePowerSql, club, tran);
                if (clubPlayers.Count > 0)
                    await conn.ExecuteAsync(playerUpdateSql, clubPlayers, tran);
                return true;
            });
        }
        
        /// <summary>
        /// 更新导出club
        /// </summary>
        public static async Task<bool> UpdateExportClubAsync(DBEntitys.ClubsDBEntity club, List<DBEntitys.ClubPlayerDBEntity> clubPlayers)
        {
            string playerUpdateSql = "UPDATE TOP(1) players SET myclubinfodata=@myclubinfodata, joinclubinfodata=@joinclubinfodata WHERE userid2018 = @userid2018";
            string clubUpdateSql = "UPDATE TOP(1) clubs SET mans=@mans, manCnt=@manCnt, wayVer=@wayVer, newways=@newways WHERE ID = @ID";
            return await GameDB.Instance.DapperExecuteTransactionAsync(dbbase.game2018, async (conn, tran) =>
            {
                await conn.ExecuteAsync(clubUpdateSql, club, tran);
                await conn.ExecuteAsync(playerUpdateSql, clubPlayers, tran);
                return true;
            });
        }

        #endregion

        #region clubs

        public static async Task<bool> UpdateClubSettingAsync(int clubId, ClubSetting setting)
        {
            if (setting == null) return false;

            clubId = clubId - IdIncrement;
            string settingJson = JsonPack.GetJson(setting);
            string sql = "UPDATE TOP(1) clubs SET [setting] = @Setting WHERE [id] = @ClubId";

            int result = await GameDB.Instance.DapperExecuteAsync(dbbase.game2018, sql,
                new { ClubId = clubId, Setting = settingJson });
            return result > 0;
        }

        #endregion
    }
}