using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Quartz;
using SolarPower.Models;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace SolarPower.Quartz.Jobs
{
    [DisallowConcurrentExecution]
    public class ExceptionSchedule : IJob
    {
        private readonly ILogger<ExceptionSchedule> logger;
        private readonly IOverviewRepository overviewRepository;
        private readonly INoticeScheduleRepository noticeScheduleRepository;
        private readonly IUserRepository userRepository;
        private readonly IPowerStationRepository powerStationRepository;
        private readonly IConfiguration Configuration;

        public ExceptionSchedule(ILogger<ExceptionSchedule> logger, IOverviewRepository overviewRepository,INoticeScheduleRepository noticeScheduleRepository,IUserRepository userRepository,IPowerStationRepository powerStationRepository, IConfiguration Configuration)
        {
            this.logger = logger;
            this.overviewRepository = overviewRepository;
            this.noticeScheduleRepository = noticeScheduleRepository;
            this.userRepository = userRepository;
            this.powerStationRepository = powerStationRepository;
            this.Configuration = Configuration;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                var ExceptionTimes = this.Configuration.GetValue<int>("ExceptionTimes");
                var ExceptionTimes_Priority1 = this.Configuration.GetValue<int>("ExceptionTimes_Priority1");
                var ExceptionTimes_Priority2 = this.Configuration.GetValue<int>("ExceptionTimes_Priority2");
                var ExceptionTimes_Priority3 = this.Configuration.GetValue<int>("ExceptionTimes_Priority3");
                var ExceptionList = await overviewRepository.GetEmailExceptionList();
                if(ExceptionList.Count > 0 )
                {
                    // 立刻發報
                    var ExceptionListex = ExceptionList.Where(x => x.priority == 1 ).ToList();
                    // 12小時後發報
                    var ExceptionListex2 = ExceptionList.Where(x => x.sourceState == 1 && x.priority == 2 &&
                                                                   (DateTime.Now.Subtract(DateTime.Parse(x.dev_time)).TotalMinutes) >= ExceptionTimes_Priority2).ToList();
                    // 24小時後發報
                    var ExceptionListex3 = ExceptionList.Where(x => x.sourceState == 1 && x.priority == 3 &&
                                                                   (DateTime.Now.Subtract(DateTime.Parse(x.dev_time)).TotalMinutes) >= ExceptionTimes_Priority3).ToList();
                    ExceptionListex.AddRange(ExceptionListex2);
                    ExceptionListex.AddRange(ExceptionListex3);

                    foreach (var Exception in ExceptionListex)
                    {
                        var UserListWithPowerstation = await overviewRepository.GetUserListWithPowerstation(Exception.PowerStationId); 
                        var Content = $"發生時間:{Exception.dev_time}" + "<br>" +
                                $"電站名稱:{Exception.PowerStationName}" + "<br>" +
                                $"異常類別:{Exception.alarmClassName}" + "<br>" +
                                $"異常訊息:{Exception.errMsg}" + "<br>" +
                                $"設備編號:{Exception.errDevice}" + "<br>" +
                                $"異常編號:{Exception.id}" + "<br>";
                        //if (Exception.errMsgT == "d")
                        //{
                        //    Content += $"當前數值:{Exception.errValue}" + "<br>";
                        //}

                        foreach (var user in UserListWithPowerstation)
                        {
                            var getCompany = noticeScheduleRepository.GetCompanyNameById(user.Id);
                            string companyName = getCompany.Result;
                            NoticeSchedule DaySchedule = new NoticeSchedule()
                            {
                                UserId = user.Id,
                                EmailType = 4,
                                RecipientEmail = user.Email,
                                Subject = "太陽能監控系統異常通知-" + Exception.PowerStationName + "-" + Exception.alarmClassName,
                                Content = Content,
                                RecipientName = user.Name,
                                Type = 1,
                                ExceptionId = Exception.id
                            };
                            List<string> properties = new List<string>()
                            {
                                "UserId",
                                "EmailType",
                                "RecipientEmail",
                                "Subject",
                                "Content",
                                "RecipientName",
                                "Type",
                                "ExceptionId"
                            };
                            await noticeScheduleRepository.AddOneAsync(DaySchedule, properties);                            
                        }

                        var powerstation = await powerStationRepository.GetOneAsync(Exception.PowerStationId);
                        if (powerstation.line_token != null)
                        {
                            Content = " %0D%0A " + Content.Replace("<br>", " %0D%0A ");
                            CallLineToken(Content, powerstation.line_token);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                logger.LogError("【{0}】{1}", nameof(logger), exception.Message);
            }
        }

        public string CallLineToken(string message, string LineToken)
        {
            try
            {
                HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create("https://notify-api.line.me/api/notify?message=" + message);
                Postrequest.Method = "POST";
                Postrequest.Headers.Add("Authorization", "Bearer " + LineToken);
                Postrequest.PreAuthenticate = true;
                HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
                var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
                var final = JObject.Parse(responseString);
                var get = final["status"].ToString();
                if (get != "200")
                {
                    logger.LogError("CallLineToken發送Line接收失敗");
                    //Logger.LogError("【" + controllerName + "/" + actionName + "】" + "CallLineToken發送Line接收失敗");
                }
                return get;
            }
            catch (Exception ex)
            {
                logger.LogError("【{0}】CallLineToken: {1}", nameof(logger), ex.Message);
                //Logger.LogError("【" + controllerName + "/" + actionName + "】" + "CallLineToken:" + ex);
                throw ex;
            }
        }

    }
}