using BBWY.Common.Models;
using BBWY.Server.Model.Db.Statistics;
using System;
using System.Collections.Concurrent;
using System.Linq;
using Yitter.IdGenerator;

namespace BBWY.Server.Business
{
    public class APIExecutionTimesRecorder : BaseBusiness, IDenpendency
    {
        private ConcurrentDictionary<string, int> apiDictionary;
        public APIExecutionTimesRecorder(IFreeSql fsql,
                                         NLogManager nLogManager,
                                         IIdGenerator idGenerator) : base(fsql, nLogManager, idGenerator)
        {
            this.apiDictionary = new ConcurrentDictionary<string, int>();
        }

        public void Record(string api)
        {
            try
            {
                apiDictionary.AddOrUpdate(api, 1, (k, v) => v + 1);
            }
            catch { }
        }

        public void Flush()
        {
            var currentRoundList = apiDictionary.Select(kv => new { Api = kv.Key, Count = kv.Value }).ToList();
            apiDictionary.Clear();
            var currentRoundKeyList = currentRoundList.Select(x => x.Api).ToList();
            var today = DateTime.Now.Date;
            var dbList = fsql.Select<ApiExecutionTimes>().Where(x => currentRoundKeyList.Contains(x.Api) && x.Date == today).ToList();

            var insertList = currentRoundList.Where(x => !dbList.Any(y => y.Api == x.Api)).Select(x => new ApiExecutionTimes
            {
                Id = idGenerator.NewLong(),
                Api = x.Api,
                Count = x.Count,
                CreateTime = DateTime.Now,
                Date = today,
                UpdateTime = DateTime.Now
            }).ToList();

            var updateList = currentRoundList.Where(x => dbList.Any(y => y.Api == x.Api))
                                             .Select(x => fsql.Update<ApiExecutionTimes>()
                                                              .Set(a => a.Count + x.Count)
                                                              .Set(a => a.UpdateTime, DateTime.Now)
                                                              .Where(a => a.Api == x.Api && a.Date == today))
                                             .ToList();

            fsql.Transaction(() =>
            {
                if (insertList.Count() > 0)
                    fsql.Insert(insertList).ExecuteAffrows();
                if (updateList.Count() > 0)
                {
                    foreach (var update in updateList)
                        update.ExecuteAffrows();
                }
            });
        }
    }
}