using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LolDataRequestLib.ResponseData
{
    internal class 골드차이팀 : AResponseData
    {
     
        protected override DataTable buildDataForResponse(BsonDocument recvDocument)
        {
            List<BsonElement> bufPlayerDataList = null;

            if (recvDocument != null)
            {
                bufPlayerDataList = recvDocument.Elements.ToList();
            }
            
            DataTable goldData = new DataTable();

            goldData.TableName = DBDefine.요청데이터분류.골드차이팀.ToString();

            goldData.Columns.Add("블루팀골드량");
            goldData.Columns.Add("레드팀골드량");
            goldData.Columns.Add("골드차");
            goldData.Columns.Add("골드차블루최대");
            goldData.Columns.Add("골드차레드최대");
            goldData.Columns.Add("초");

            int 골드차블루최대값 = 0;

            int 골드차레드최대값 = 0;


            foreach (BsonElement item in bufPlayerDataList)
            {
                DataRow bufRow = goldData.NewRow();

                BsonArray itemValue = item.Value.ToBsonDocument()["teams"].AsBsonArray;

                int 블루팀골드 = 0;
                int 레드팀골드 = 0;

                foreach (BsonValue itemTeam in itemValue)
                {
                    
                    if (itemTeam["teamID"].ToInt32() == (int)DBDefine.팀구분.블루)
                    {
                        블루팀골드 = itemTeam["totalGold"].ToInt32();
                    }
                    else
                    {
                        레드팀골드 = itemTeam["totalGold"].ToInt32();
                    }

                }

                bufRow["블루팀골드량"] = 블루팀골드;
                bufRow["레드팀골드량"] = 레드팀골드;
                bufRow["골드차"] = 블루팀골드 - 레드팀골드;

                if (골드차블루최대값 < (블루팀골드 - 레드팀골드))
                {
                    골드차블루최대값 = (블루팀골드 - 레드팀골드);
                }

                if (골드차레드최대값 < (레드팀골드 - 블루팀골드))
                {
                    골드차레드최대값 = (레드팀골드 - 블루팀골드);
                }

                bufRow["골드차블루최대"] = 골드차블루최대값;
                bufRow["골드차레드최대"] = 골드차레드최대값 * -1;

                bufRow["초"] = item.Value["gameTime"].ToInt32() / 1000;
                goldData.Rows.Add(bufRow);

            }

            return goldData;

        }

        protected override BsonDocument getDataFromMongo()
        {
            // 필요한 필드만 포함하는 필터 문서를 생성합니다.
            var subFilter = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{'eventDocument.playbackID' : 1, 'eventDocument.teams.totalGold' : 1, 'eventDocument.teams.teamID' : 1, 'eventDocument.sequenceIndex' : 1, " +
                "'eventDocument.gameTime' : 1, 'eventDocument.parentGameID': 1, 'eventDocument.repeater_timestamp': 1}");

            //var subFilter = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{'eventDocument.playbackID' : 1, 'eventDocument.teams.totalGold' : 1, 'eventDocument.teams.teamID' : 1,'eventDocument.sequenceIndex' : 1, 'eventDocument.gameTime' : 1}");
            
            // MongoDB 컬렉션 "stats_update"에서 전체 문서를 가져오고 필요한 필드만 Projection합니다.
            List<BsonDocument> documents = mEventDataBase.GetCollection<BsonDocument>("stats_update")
                .Find(new BsonDocument())
                .Project(subFilter)
                .ToList();

            //documents = documents.OrderBy(r => r["eventDocument"]["sequenceIndex"].ToInt32()).ToList();
            documents = documents.OrderBy(r => DateTime.Parse(r["eventDocument"]["repeater_timestamp"].AsString)).ToList();

            BsonDocument rtnValue = new BsonDocument();

            // 이전 이벤트의 RequestGameID를 저장할 변수입니다.
            string previousRequestGameID = null;

            foreach (BsonDocument item in documents)
            {
                try
                {
                    // 현재 이벤트의 RequestGameID 값을 추출합니다.
                    string currentRequestGameID = item["eventDocument"]["parentGameID"].ToString();

                    // 롤백 상황 감지:
                    // 이전 이벤트의 RequestGameID가 존재하고, 현재 이벤트의 값과 다르다면
                    // 이는 롤백 후 새로운 게임 데이터가 들어왔음을 의미합니다.
                    if (previousRequestGameID != null && !currentRequestGameID.Equals(previousRequestGameID))
                    {
                        // 현재 이벤트의 gameTime을 롤백 기준으로 설정합니다.
                        int rollbackThreshold = item["eventDocument"]["gameTime"].ToInt32();
                        // 지금까지 모아둔 데이터(rtnValue) 중 gameTime이 rollbackThreshold 미만인 이벤트만 유지합니다.
                        List<BsonElement> filteredElements = rtnValue.ToList()
                            .Where(d => d.Value["gameTime"].ToInt32() < rollbackThreshold)
                            .ToList();
                        rtnValue = new BsonDocument(filteredElements);
                    }

                    // 현재 이벤트 정보를 새 BsonDocument로 준비합니다.
                    BsonDocument bufDocument = new BsonDocument();
                    bufDocument.Add("gameTime", item["eventDocument"]["gameTime"].ToInt32());
                    bufDocument.Add("teams", item["eventDocument"]["teams"].AsBsonArray);
                    bufDocument.Add("playback", item["eventDocument"]["playbackID"].ToString());

                    bufDocument.Add("parentGameID", item["eventDocument"]["parentGameID"]);

                    // sequenceIndex 값을 Key로 하여 해당 이벤트를 rtnValue에 추가합니다.
                    rtnValue.Add(item["eventDocument"]["sequenceIndex"].ToString(), bufDocument);

                    // 다음 반복을 위해 이전 RequestGameID를 업데이트합니다.
                    previousRequestGameID = currentRequestGameID;
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

            return rtnValue; 
        }
    }
}
