using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Log;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Repository;
using System;
using System.Linq;
using System.Threading;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Repository.Entities;

namespace Siger.ApiTPM.Tasks
{
    public class AutoCreateCalenderHelper : IDisposable
    {
        private static AutoCreateCalenderHelper _helper;
        public static AutoCreateCalenderHelper Instance = _helper ?? (_helper = new AutoCreateCalenderHelper());

        private static ApiConfigDbContext _context;
        public AutoCreateCalenderHelper()
        {
            
        }

        public void StartTask()
        {
            try
            {
                var thread = new Thread(Process)
                {
                    IsBackground = true
                };
                thread.Start();
            }
            catch (Exception e)
            {
                Logger.WriteLineError("AutoCreateCalender failed, error:" + e);
            }
        }

        private void Process()
        {
            while (true)
            {
                Thread.Sleep(1000 * 60 * 60 * 12); // 1天

                Execute();
            }
        }

        private void Execute()
        {
            try
            {
                if (RedisCache.Client == null)
                {
                    RedisCache.Connect();
                }
            }
            catch (Exception e)
            {
                Logger.WriteLineInfo($"Redis connect error:" + e);
            }
            var dbConfigs = RedisCache.Instance.GetDbNameConfigs();
            if (dbConfigs.Any())
            {
                _context = new ApiConfigDbContext();
                foreach (var dbNameConfig in dbConfigs)
                {
                    if (string.IsNullOrWhiteSpace(dbNameConfig.RedisDbName))
                    {
                        Logger.WriteLineError($"AutoSyncTpm DbNameConfig setting error, can not find redisdbname by cid:{dbNameConfig.Cid}, pid:{dbNameConfig.Pid}.");
                        continue;
                    }
                    ExcuteCreateAction(dbNameConfig.Pid);
                }
                Dispose();
            }
        }

        private void ExcuteCreateAction(int projectId)
        {
            var cals = _context.siger_project_working_calendar.Where(q => q.project_id == projectId);
            if (!cals.Any())
            {
                return;
            }
               
            var maxDate = cals.Max(q => q.date);
            if(maxDate > DateTime.Now.Date)
            {
                return;
            }

            var startDate = DateTime.Now.ToString(ParameterConstant.MouthFirstDay).ToDateTime().Date;
            var endDate = DateTime.Now.ToString(ParameterConstant.MouthFirstDay).ToDateTime().AddMonths(1).AddDays(-1).Date;

            var allUserids = cals.Select(m => m.user_mid).Distinct().ToList();
            var allMachineids = cals.Select(m => m.machine_id).Distinct().ToList();
            foreach (var userId in allUserids)
            {
                var workGroup = _context.siger_project_working_group.FirstOrDefault(q => (q.user_mids + ",").Contains(userId + ",") && q.project_id == projectId
                && q.status == (int)RowState.Valid);
                if (workGroup == null) continue;

                var shiftIds = workGroup.shift_ids.TrimEnd(',').Split(',').Select(x => x.ToInt()).ToList();
                foreach (var machineId in allMachineids)
                {
                    DateTime dtDay = startDate;
                    var entity = _context.siger_project_working_calendar.FirstOrDefault(q => q.user_mid == userId && q.machine_id == machineId
                                    && q.date == dtDay && q.project_id == projectId && q.status == (int)RowState.Valid);
                    if(entity != null)
                    {
                        continue;
                    }

                    var i = startDate.Subtract(workGroup.start_date).TotalDays % workGroup.interval;
                    for (dtDay = startDate; dtDay.CompareTo(endDate) <= 0; dtDay = dtDay.AddDays(1).Date)
                    {
                        if (i == workGroup.interval)
                        {
                            i = 0;
                        }

                        var cal = new siger_project_working_calendar
                        {
                            user_mid = userId,
                            machine_id = machineId,
                            date = dtDay.Date,
                            project_id = projectId,
                            shift_id = shiftIds[i.ToStr().ToInt()]
                        };
                        _context.siger_project_working_calendar.Add(cal);
                        i++;
                    }
                }
            }

            _context.SaveChanges();
        }

        public void Dispose()
        {
            _context?.Dispose();
        }
    }
}
