using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Quartz;
using SolarPower.Models;
using SolarPower.Models.User;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace SolarPower.Quartz.Jobs
{
    [DisallowConcurrentExecution]
    public class OperationScheduleJob : IJob
    {
        private readonly ILogger<OperationScheduleJob> logger;
        private IOperationRepository operationRepository;
        private readonly IPowerStationRepository powerStationRepository;
        private readonly IUserRepository userRepository;
        private readonly INoticeScheduleRepository noticeScheduleRepository;
        private readonly IStationReportRepository stationReportRepository;

        public OperationScheduleJob(ILogger<OperationScheduleJob> logger,
                            IOperationRepository operationRepository,
                            IPowerStationRepository powerStationRepository,
                            IUserRepository userRepository,
                            INoticeScheduleRepository noticeScheduleRepository,
                            IStationReportRepository stationReportRepository)
        {
            this.logger = logger;
            this.operationRepository = operationRepository;
            this.powerStationRepository = powerStationRepository;
            this.userRepository = userRepository;
            this.noticeScheduleRepository = noticeScheduleRepository;
            this.stationReportRepository = stationReportRepository;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                var getTime = await operationRepository.GetOperationSchedules();
                foreach (var a in getTime)
                {
                    //最後製作紀錄時間
                    var useday = a.LastCreateTime;
                    if (a.LastCreateTime == "0001-01-01 00:00:00")
                    {
                        useday = a.StartTime;
                    }

                    #region 產生紀錄
                    DateTime Updatedtime;//下次生成紀錄時間
                    Updatedtime = a.ScheduleType switch
                    {
                        0 => Convert.ToDateTime(useday).AddDays(a.ScheduleNum),
                        1 => Convert.ToDateTime(useday).AddDays(a.ScheduleNum * 7),
                        2 => Convert.ToDateTime(useday).AddMonths(a.ScheduleNum),
                        3 => Convert.ToDateTime(useday).AddMonths(a.ScheduleNum * 3),
                        4 => Convert.ToDateTime(useday).AddYears(a.ScheduleNum),
                        _ => Convert.ToDateTime(useday).AddYears(999)
                    };

                    if (Updatedtime < DateTime.Now)
                    {
                        var now = DateTime.Now.ToString("yyyy-MM-dd");
                        var OperationPlan = new OperationCreatePlan()
                        {
                            Id = a.Id,
                            EmailType = a.EmailType,
                            ScheduleNum = a.ScheduleNum,
                            Description = a.Description,
                            WorkDay = a.WorkDay,
                            ScheduleType = a.ScheduleType,
                            StartTime = useday,
                            PowerStationId = a.PowerStationId,
                            Type = a.Type,
                            UpdatedBy = a.UpdatedBy,
                            LastCreateTime = Updatedtime.ToString("yyyy-MM-dd"),
                            IsDelivery = 0
                        };
                        List<string> properties = new List<string>()
                        {
                            "Id",
                            "EmailType",
                            "ScheduleNum",
                            "Description",
                            "WorkDay",
                            "ScheduleType",
                            "StartTime",
                            "PowerStationId",
                            "Type",
                            "UpdatedBy",
                            "LastCreateTime",
                            "IsDelivery"
                        };
                        await operationRepository.UpdateOperationPlan(OperationPlan, properties);



                        string endtime = "";
                        switch (a.ScheduleType)
                        {
                            case 0:
                                endtime = (Convert.ToDateTime(Updatedtime.ToString("yyyy-MM-dd")).AddDays(a.ScheduleNum)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 1:
                                endtime = (Convert.ToDateTime(Updatedtime.ToString("yyyy-MM-dd")).AddDays(a.ScheduleNum * 7)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 2:
                                endtime = (Convert.ToDateTime(Updatedtime.ToString("yyyy-MM-dd")).AddMonths(a.ScheduleNum)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 3:
                                endtime = (Convert.ToDateTime(Updatedtime.ToString("yyyy-MM-dd")).AddMonths(a.ScheduleNum * 3)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 4:
                                endtime = (Convert.ToDateTime(Updatedtime.ToString("yyyy-MM-dd")).AddYears(a.ScheduleNum * 3)).ToString("yyyy-MM-dd 00:00:00"); break;
                        }
                        var record = new PlanToRecord()
                        {
                            WorkType = a.Type,
                            PowerStationId = a.PowerStationId,
                            StartTime = a.StartTime,
                            CreatedBy = a.CreatedBy,
                            EndTime = endtime,
                            Notice = a.Description
                        };
                        List<string> properties2 = new List<string>()
                        {
                            "WorkType",
                            "PowerStationId",
                            "StartTime",
                            "CreatedBy",
                            "EndTime",
                            "Notice"
                        };

                        await operationRepository.AddToRecord(record, properties2);

                    }

                    #endregion




                    #region 發送Email
                    DateTime EmailNoticeDay;
                    string noticeName;
                    EmailNoticeDay = a.EmailType switch
                    {
                        0 => Updatedtime,
                        1 => Updatedtime.AddDays(-1),
                        2 => Updatedtime.AddDays(-2),
                        3 => Updatedtime.AddDays(-3),
                        4 => Updatedtime.AddDays(-7),
                        _ => Updatedtime.AddYears(999)
                    };
                    noticeName = a.EmailType switch
                    {
                        0 => "此紀錄於當天建立",
                        1 => "此紀錄於一天後建立",
                        2 => "此紀錄於兩天後建立",
                        3 => "此紀錄於三天後建立",
                        4 => "此紀錄於一週後建立",
                        _ => "此紀錄不建立"
                    };
                    string WorkType = a.Type switch
                    {
                        0 => "清洗",
                        1 => "巡檢",
                        _ => "維修"
                    };
                    if(EmailNoticeDay < DateTime.Now && a.IsDelivery == 0)
                    {
                        //Get所有運維人員
                        var personal = await operationRepository.GetOperationPersonnel(a.PowerStationId);
                        var Title = $@"電站:{a.PowerStationName} - {WorkType}單 - 編號:{a.PlanId}";
                        var content = $@" {noticeName}  {Environment.NewLine} 內容描述:{a.Description}";
                        await operationRepository.InsertNoticeSchedule(personal, Title, content, 3);

                        var OperationPlans = new OperationCreatePlan()
                        {
                            Id = a.Id,
                            IsDelivery = 1
                        };
                        List<string> propertiess = new List<string>()
                        {
                            "Id",
                            "IsDelivery"
                        };
                        await operationRepository.UpdateOperationPlan(OperationPlans, propertiess);
                    }

                    
                    #endregion


                }

                #region 寄送日月報
                var users = userRepository.GetAllAsync();

                //var usertest = new List<User>();
                //var oneuser = new User()
                //{
                //    Account = "cesarliuc@gmail.com",
                //    Password = "np/F0eliIy3lPJe1tU18oiG7dzKRrpVw16/XZpHOph8=",
                //    Id = 13,
                //    Email = "cesarliuc@gmail.com",
                //    Status = 1,
                //    Name = "TEST"
                //};
                //usertest.Add(oneuser);

                //var ttt = new List<string>() {
                //    "s506488@gmail.com",
                //    "cesarliuc@gmail.com"
                //};



                foreach (var user in users.Result)
                {
                    try
                    {
                        logger.LogInformation("【OperationScheduleJob】【開始產生使用者[{0}({1})]的日月報】", user.Account, user.Name);

                        List<OperationPersonnel> powerstations = new List<OperationPersonnel>();
                        powerstations = await noticeScheduleRepository.GetPowerStationOperationPersonnel(user.Id);
                        if (powerstations.Count == 0)
                        {
                            continue;
                        }
                        List<Excelpowerstation> sentdaypowerstations = powerstations.Where(x => x.EmailDayReport == 1).Select(a => new Excelpowerstation { Name = a.Name, Value = a.PowerStationId.ToString() }).ToList();
                        List<Excelpowerstation> sentMaxpowerstations = powerstations.Where(x => x.EmailComplexReport == 1).Select(a => new Excelpowerstation { Name = a.Name, Value = a.PowerStationId.ToString() }).ToList();

                        Controllers.StationReportController stationReportController = new Controllers.StationReportController(powerStationRepository, stationReportRepository);
                        //日報表
                        if (sentdaypowerstations.Count != 0)
                        {
                            Excel dayexcel = new Excel()
                            {
                                FormType = 0,
                                PowerStation = sentdaypowerstations,
                                SearchType = 0,
                                Time = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd"),
                                Userid = user.Id
                            };
                            var stationReportName = stationReportController.ExportExcelBackDownload(JsonConvert.SerializeObject(dayexcel, Formatting.Indented));
                            if (stationReportName != "")
                            {
                                if (IsValidEmail(user.Email))
                                {
                                    NoticeSchedule DaySchedule = new NoticeSchedule()
                                    {
                                        UserId = user.Id,
                                        EmailType = 0,
                                        RecipientEmail = user.Email,
                                        Subject = "日報表",
                                        Attachment = stationReportName,
                                        RecipientName = user.Name,
                                        Type = 1
                                    };
                                    List<string> properties = new List<string>()
                                    {
                                        "UserId",
                                        "EmailType",
                                        "RecipientEmail",
                                        "Subject",
                                        "Attachment",
                                        "RecipientName",
                                        "Type"
                                    };
                                    await noticeScheduleRepository.AddOneAsync(DaySchedule, properties);
                                }
                            }
                        }
                        //綜合報表 每日
                        if (sentMaxpowerstations.Count != 0)
                        {
                            Select_table2 maxdayexcel = new Select_table2()
                            {
                                FormType = 0,
                                PowerStation = sentMaxpowerstations,
                                SearchType = 0,
                                Time = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd"),
                                Userid = user.Id
                            };
                            var stationMaxReportName = stationReportController.ExportExcelmaxtableBackDownload(JsonConvert.SerializeObject(maxdayexcel, Formatting.Indented));
                            if (IsValidEmail(user.Email))
                            {
                                NoticeSchedule MaxSchedule = new NoticeSchedule()
                                {
                                    UserId = user.Id,
                                    EmailType = 2,
                                    RecipientEmail = user.Email,
                                    Subject = "綜合報表",
                                    Attachment = stationMaxReportName,
                                    RecipientName = user.Name,
                                    Type = 1
                                };
                                List<string> properties = new List<string>()
                                {
                                    "UserId",
                                    "EmailType",
                                    "RecipientEmail",
                                    "Subject",
                                    "Attachment",
                                    "RecipientName",
                                    "Type"
                                };
                                await noticeScheduleRepository.AddOneAsync(MaxSchedule, properties);
                            }

                            if (DateTime.Now.ToString("dd") == "01")
                            {
                                Select_table2 maxmonthexcel = new Select_table2()
                                {
                                    FormType = 1,
                                    PowerStation = sentMaxpowerstations,
                                    SearchType = 1,
                                    Time = DateTime.Now.AddDays(-1).ToString("yyyy-MM"),
                                    Userid = user.Id
                                };
                                var stationReportmaxmonthName = stationReportController.ExportExcelBackDownload(JsonConvert.SerializeObject(maxmonthexcel, Formatting.Indented));
                                if (IsValidEmail(user.Email))
                                {
                                    NoticeSchedule MaxmonthSchedule = new NoticeSchedule()
                                    {
                                        RecipientEmail = user.Email,
                                        Subject = "綜合報表",
                                        Attachment = stationReportmaxmonthName,
                                        RecipientName = user.Name,
                                        Type = 1,
                                        UserId = user.Id,
                                        EmailType = 2
                                    };
                                    List<string> properties2 = new List<string>()
                                    {
                                        "UserId",
                                        "EmailType",
                                        "RecipientEmail",
                                        "Subject",
                                        "Attachment",
                                        "RecipientName",
                                        "Type"
                                    };
                                    await noticeScheduleRepository.AddOneAsync(MaxmonthSchedule, properties2);
                                }
                            }

                        }

                        if (DateTime.Now.ToString("dd") == "01")
                        {
                            List<Excelpowerstation> sentmonthpowerstations = powerstations.Where(x => x.EmailMonthReport == 1).Select(a => new Excelpowerstation { Name = a.Name, Value = a.PowerStationId.ToString() }).ToList();
                            if (sentmonthpowerstations.Count == 0)
                            {
                                break;
                            }
                            Excel monthexcel = new Excel()
                            {
                                FormType = 1,
                                PowerStation = sentmonthpowerstations,
                                SearchType = 2,
                                Time = DateTime.Now.AddDays(-1).ToString("yyyy-MM"),
                                Userid = user.Id
                            };
                            var stationReportmonthName = stationReportController.ExportExcelBackDownload(JsonConvert.SerializeObject(monthexcel, Formatting.Indented));
                            if (stationReportmonthName != "")
                            {
                                if (IsValidEmail(user.Email))
                                {
                                    NoticeSchedule MonthSchedule = new NoticeSchedule()
                                    {
                                        RecipientEmail = user.Email,
                                        Subject = "月報表",
                                        Attachment = stationReportmonthName,
                                        RecipientName = user.Name,
                                        Type = 1,
                                        UserId = user.Id,
                                        EmailType = 1
                                    };
                                    List<string> properties2 = new List<string>()
                                    {
                                        "UserId",
                                        "EmailType",
                                        "RecipientEmail",
                                        "Subject",
                                        "Attachment",
                                        "RecipientName",
                                        "Type"
                                    };
                                    await noticeScheduleRepository.AddOneAsync(MonthSchedule, properties2);
                                }
                            }

                        }

                        logger.LogInformation("【OperationScheduleJob】【產生完成使用者[{0}({1})]的日月報】", user.Account, user.Name);
                    }
                    catch (Exception exception)
                    {
                        logger.LogError("【OperationScheduleJob】【產生失敗使用者[{0}({1})]的日月報】", user.Account, user.Name);
                        logger.LogError("【OperationScheduleJob】[Exception] - {0}", exception.Message);
                        if (exception.InnerException != null)
                        {
                            logger.LogError("【OperationScheduleJob】[InnerException] - {0}", exception.InnerException.Message);
                        }

                        var line = new StackTrace(exception, true).GetFrame(0).GetFileLineNumber();
                        logger.LogError("【OperationScheduleJob】[錯誤行數] - {0}", line);
                    }
                }

                #endregion
            }
            catch (Exception exception)
            {
                logger.LogError("【{0}】{1}", nameof(logger), exception.Message);
            }
        }

        /// <summary>
        /// 取得最新的流水號
        /// </summary>
        /// <param name="current">當前的</param>
        /// <param name="pad"></param>
        /// <param name="direction">0: PadLeft；1: PadRight</param>
        /// <returns></returns>
        public string GetLastSerialNumber(string current = "", int pad = 4, byte direction = 0)
        {
            var tempSerialNumber = 0;
            if (!string.IsNullOrEmpty(current))
            {
                tempSerialNumber = Convert.ToInt32(current) + 1;
            }
            else
            {
                tempSerialNumber = 1;
            }

            if (direction == 0)
            {
                return tempSerialNumber.ToString().Trim().PadLeft(pad, '0');
            }
            else
            {
                return tempSerialNumber.ToString().Trim().PadRight(pad, '0');
            }
        }

        bool IsValidEmail(string strIn)
        {
            // Return true if strIn is in valid e-mail format.
            return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }
    }
}
