using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Siger.ApiTPM.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Repository.Data.Tpm;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.TpmRepository;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Response;

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

        private static ApiTpmDbContext _context;
        public SparepartTask()
        {
            _context = new ApiTpmDbContext();
        }

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

        private void Process()
        {
            while (true)
            {
                Thread.Sleep(1000 * 60 * 1); // 1分钟
                var now = DateTime.Now;
                //每天的3:00执行
                if (now.Hour == 3 && now.Minute == 0)
                {
                    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 ApiTpmDbContext();
                foreach (var dbNameConfig in dbConfigs)
                {
                    if (string.IsNullOrWhiteSpace(dbNameConfig.RedisDbName))
                    {
                        Logger.WriteLineError($"SparepartTask DbNameConfig setting error, can not find redisdbname by cid:{dbNameConfig.Cid}, pid:{dbNameConfig.Pid}.");
                        continue;
                    }
                    GetNoticeData(dbNameConfig.Pid);
                }
                Dispose();
            }
        }

        private void GetNoticeData(int pid)
        {
            var cycle = _context.siger_project_procurement_process.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid == pid)?.cycle ?? 0;
            var query = _context.siger_project_sparepart.Where(f => f.projectid.Equals(pid) && f.status == (int)RowState.Valid);
            var querylist = from q in query
                            join ty1 in _context.siger_project_sparepart_type on q.typeid equals ty1.id into type1
                            from ty1 in type1.DefaultIfEmpty()
                            select new ResponseSparepartInfo
                            {
                                brand = q.brand,
                                code = q.code,
                                max_sku = q.max_sku,
                                mini_sku = q.mini_sku,
                                sku = q.sku,
                                sku_limit = q.sku_limit,
                                title = q.title,
                                type_id = q.typeid,
                                type = ty1.title,
                                mid = ty1.userId,
                                id = q.id,
                                last_order_time = q.order_time,
                                count = q.sku_limit//库存采购量
                            };
            foreach (var item in querylist.ToList())
            {
                var count = item.sku - item.mini_sku;
                var detail = _context.siger_project_sparepart_order_detail.Where(f => f.projectid.Equals(pid) && f.status == (int)RowState.Valid && f.sparepart_code.Equals(item.code));
                if (detail.Any())
                {
                    count += detail.Sum(s => s.count);
                }
                var start = item.last_order_time == 0 ? UnixTimeHelper.GetNow() : item.last_order_time;
                var end = start + 86400 * cycle;
                var last_week = GetSparepartCount(item.id, (int)start, (int)end, 2, pid);
                if (count <= last_week)
                {
                    var sparepart = $"{item.title}:{item.code}";
                    SendAlarmMail(item.mid, sparepart, "系统采购通知", pid);
                }
            }
        }
        private void SendAlarmMail(int mid, string sparepart, string head, int pid)
        {
            var Cfg = _context.siger_project_email_config.FirstOrDefault(f => f.project == pid && f.status == (int)RowState.Valid);
            if (Cfg == null)
            {
                Logger.WriteLineInfo("你没有维护邮箱！");
                return;
            }
            var user = _context.siger_project_user.FirstOrDefault(f => f.mid.Equals(mid) && f.status == (int)RowState.Valid);
            if (user == null || string.IsNullOrEmpty(user.work_email))
            {
                Logger.WriteLineInfo($"{mid}该用户没有邮箱！");
                return;
            }
            var content = $"尊敬的{user.name}您好，\r\n您所负责的备件:{sparepart}\r\n库存已超过预警值，请及时进行在系统进行采购";
            if (string.IsNullOrEmpty(user.work_email))
            {
                return;
            }
            MailHelper.SendMail(Cfg.server, true, Cfg.send, Cfg.code, "Tpm Notice",
                   Cfg.send, user.work_email, head, content, new List<string>());
        }
        private int GetSparepartCount(int sparepartId, int startTime, int endTime, int type, int pid)
        {
            var count = _context.siger_project_sparepart_record.Where(q => q.sparepartid == sparepartId && q.type == type
                                                                                    && q.create_time >= startTime && q.create_time < endTime
                                                                                    && q.projectid == pid && q.status == (int)RowState.Valid)
                .Sum(q => q.number);

            return count;
        }

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