using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Quartz;
using SolarPower.Models.PowerStation;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace SolarPower.Quartz.Jobs
{
    [DisallowConcurrentExecution]
    public class CalcPowerStationJob : IJob
    {
        private readonly ILogger<CalcPowerStationJob> logger;
        private readonly IPowerStationRepository powerStationRepository;

        public IWebHostEnvironment environment;

        private double carbonRate;

        public CalcPowerStationJob(
            ILogger<CalcPowerStationJob> logger,
            IPowerStationRepository powerStationRepository,
            IWebHostEnvironment environment)
        {
            this.logger = logger;
            this.powerStationRepository = powerStationRepository;
            this.environment = environment;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                var DateTimeNow = DateTime.Now;
                var dateTime = DateTimeNow.AddHours(-1).ToString("yyyy-MM-dd HH");

                Root2 observation = null;

                if (this.environment.IsDevelopment())
                {
                    dateTime = "2021-08-16 09";
                }

                logger.LogInformation("【CalcPowerStationJob】【任務開始】");

                #region step1. 找出所有電站
                logger.LogInformation("【CalcPowerStationJob】【開始取得電站資料】");
                var powerStations = await powerStationRepository.GetAllAsync();
                logger.LogInformation("【CalcPowerStationJob】【取得成功電站資料】");
                logger.LogInformation("【CalcPowerStationJob】【電站資料】 - {0}", System.Text.Json.JsonSerializer.Serialize(powerStations));
                #endregion

                List<PowerStationHistory> powerStationHistoriesHour = new List<PowerStationHistory>();
                List<PyrheliometerHistory> sensorHistoriesHour = new List<PyrheliometerHistory>();

                List<PyrheliometerHistory> pyrheliometerHistoriesHour = new List<PyrheliometerHistory>();
                List<PyrheliometerHistory> TempHistoriesHour = new List<PyrheliometerHistory>();
                List<InverterHistory> inverterHistoriesHour = new List<InverterHistory>();
                List<PowerStation> calcPowerStations = new List<PowerStation>();
                List<SensorAvgHistory> sensorAvgHistoryHour = new List<SensorAvgHistory>();
                List<MeterHistory> meterHistoriesHour = new List<MeterHistory>();
                List<WeatherObservation> weatherObservations = new List<WeatherObservation>();

                #region 氣象觀測(取資料)
                try
                {
                    logger.LogInformation("【CalcPowerStationJob】【開始取得氣象觀測】");
                    var client = new HttpClient();
                    var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/O-A0003-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&elementName=TIME,TEMP";
                    HttpResponseMessage response = client.GetAsync(UVUri).Result;
                    String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString();
                    observation = JsonConvert.DeserializeObject<Root2>(jsonUVs);
                    logger.LogInformation("【CalcPowerStationJob】【取得成功氣象觀測】");
                }
                catch (Exception ex)
                {
                    logger.LogError("【CalcPowerStationJob】【取得失敗氣象觀測】");
                    logger.LogError("【{0}】{1}", "CalcPowerStationJob", ex.Message);
                    observation = null;
                }
                #endregion

                #region step2. 從電站的DB及電站編號找出該電站的控制器
                foreach (var powerStation in powerStations)
                {
                    try
                    {
                        var calcPowerStation = new PowerStation();
                        calcPowerStation.Id = powerStation.Id;

                        #region step2-1. 取得該電站的當前這小時的歷史資料
                        var table_name = String.Format("s{1}01_station", powerStation.SiteDB, powerStation.Code);
                        var full_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, table_name);
                        var exist = await powerStationRepository.ExistTable(powerStation.SiteDB, table_name);

                        if (string.IsNullOrEmpty(exist))
                        {
                            logger.LogError($"【CalcPowerStationJob】【查無電站[{powerStation.Code}]的s{powerStation.Code}01_station資料表】");
                        }
                        else
                        {
                            logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime);
                            var history = await powerStationRepository.GetPowerStationHistoryPerHour(dateTime, full_table_name);
                            logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime);
                            logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的每小時歷史資料】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(history));
                            var lastmoneyhistorybyhour = await powerStationRepository.GetLastMoneyAndCarbonInHour(powerStation.Id, 0, dateTime);

                            if (history != null)
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime);
                                history.PowerStationId = powerStation.Id;
                                history.Timestamp = Convert.ToDateTime(history.Timestamp + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");

                                #region 計算單一電站每小時發電量、發電金額等資料

                                #region 發電量
                                //每小時發電量(直接填寫
                                calcPowerStation.kwh = history.KWH;
                                //今日發電量(直接填寫
                                calcPowerStation.Today_kWh = history.TodayKWh;
                                //總發電量(直接填寫
                                calcPowerStation.Total_kWh = history.TotalKWH;
                                #endregion

                                #region 發電金額

                                history.MONEY = history.KWH * powerStation.PowerRate;
                                history.TODAYMONEY = history.TodayKWh * powerStation.PowerRate;
                                history.TOTALMONEY = history.TotalKWH * powerStation.PowerRate;

                                //即時發電金額
                                switch (powerStation.SolarType)
                                {
                                    case (int)SolarTypeEnum.SelfSold: //自建躉售 

                                        //if (lastmoneyhistorybyhour != null)
                                        //{
                                        //    history.TODAYMONEY = lastmoneyhistorybyhour.TODAYMONEY + history.KWH * powerStation.PowerRate;
                                        //    history.TOTALMONEY = lastmoneyhistorybyhour.TOTALMONEY + history.KWH * powerStation.PowerRate;
                                        //}
                                        //else
                                        //{
                                        //    history.TODAYMONEY = history.KWH * powerStation.PowerRate;
                                        //    history.TOTALMONEY = history.KWH * powerStation.PowerRate;
                                        //}

                                        //今日發電金額 計算方式：todaykWh * 授電費率
                                        calcPowerStation.Today_Money = history.TodayKWh * powerStation.PowerRate;
                                        //calcPowerStation.Today_Money = history.TODAYMONEY;

                                        ////總發電金額 計算方式：totalkWh * 授電費率
                                        calcPowerStation.Total_Money = history.TotalKWH * powerStation.PowerRate;
                                        //calcPowerStation.Total_Money = history.TOTALMONEY;
                                        break;
                                    case (int)SolarTypeEnum.HireSold: //租建躉售 
                                                                      //找出該電站的所有土地房屋資訊
                                        var landBuildings = await powerStationRepository.GetAllLandBuildingInfoByPowerStationId(powerStation.Id, powerStation.SiteDB);
                                        var sumLeaseRate = 0.00;
                                        var avgLeaseRate = 0.00;

                                        foreach (var landBuilding in landBuildings)
                                        {
                                            sumLeaseRate += landBuilding.LeaseRate;
                                        }
                                        //avgLeaseRate = sumLeaseRate / landBuildings.Count();

                                        //if (lastmoneyhistorybyhour != null)
                                        //{
                                        //    history.TODAYMONEY = lastmoneyhistorybyhour.TODAYMONEY + history.KWH * powerStation.PowerRate;
                                        //    history.TOTALMONEY = lastmoneyhistorybyhour.TOTALMONEY + history.KWH * powerStation.PowerRate;

                                        //    //今日發電金額計算方式：todaykWh * 出借費率(各個土地房屋租借比率平均)
                                        //    calcPowerStation.Today_Money = lastmoneyhistorybyhour.TODAYMONEY + (history.KWH * powerStation.PowerRate * sumLeaseRate);
                                        //    //總發電金額 計算方式：totalkWh * 授電費率
                                        //    calcPowerStation.Total_Money = lastmoneyhistorybyhour.TOTALMONEY + (history.KWH * powerStation.PowerRate * sumLeaseRate);
                                        //}
                                        //else
                                        //{
                                        //    history.TODAYMONEY = history.KWH * powerStation.PowerRate;
                                        //    history.TOTALMONEY = history.KWH * powerStation.PowerRate;

                                        //    calcPowerStation.Today_Money = history.KWH * powerStation.PowerRate * sumLeaseRate;
                                        //    calcPowerStation.Total_Money = history.KWH * powerStation.PowerRate * sumLeaseRate;
                                        //}

                                        calcPowerStation.Today_Money = history.TodayKWh * powerStation.PowerRate * sumLeaseRate / 100;
                                        calcPowerStation.Total_Money = history.TotalKWH * powerStation.PowerRate * sumLeaseRate / 100;

                                        break;
                                    case (int)SolarTypeEnum.SelfUse: //自建自用 

                                        //if (lastmoneyhistorybyhour != null)
                                        //{
                                        //    history.TODAYMONEY = lastmoneyhistorybyhour.TODAYMONEY + history.KWH * powerStation.PowerRate;
                                        //    history.TOTALMONEY = lastmoneyhistorybyhour.TOTALMONEY + history.KWH * powerStation.PowerRate;
                                        //}
                                        //else
                                        //{
                                        //    history.TODAYMONEY = history.KWH * powerStation.PowerRate;
                                        //    history.TOTALMONEY = history.KWH * powerStation.PowerRate;
                                        //}

                                        //今日發電金額 計算方式：todaykWh * 授電費率
                                        //calcPowerStation.Today_Money = history.TODAYMONEY;
                                        calcPowerStation.Today_Money = history.TodayKWh * powerStation.PowerRate;

                                        //總發電金額 計算方式：totalkWh * 授電費率
                                        //calcPowerStation.Total_Money = history.TOTALMONEY;
                                        calcPowerStation.Total_Money = history.TotalKWH * powerStation.PowerRate;
                                        break;
                                }
                                #endregion

                                #region kWh/kWp
                                //直接填寫
                                calcPowerStation.Today_kwhkwp = history.KWHKWP;
                                #endregion

                                #region PR
                                //直接填寫
                                calcPowerStation.Today_PR = history.PR;
                                #endregion

                                #region 減碳量
                                carbonRate = Convert.ToDouble(await powerStationRepository.GetOneVariableByName("CarbonRate"));

                                history.CARBON = history.KWH * carbonRate;
                                history.TODAYCARBON = history.TodayKWh * carbonRate;
                                history.TOTALCARBON = history.TotalKWH * carbonRate;
                                //if (lastmoneyhistorybyhour != null)
                                //{
                                //    history.TODAYCARBON = lastmoneyhistorybyhour.TODAYCARBON + history.KWH * carbonRate;
                                //    history.TOTALCARBON = lastmoneyhistorybyhour.TOTALCARBON + history.KWH * carbonRate;
                                //}
                                //else
                                //{
                                //    history.TODAYCARBON = history.KWH * carbonRate;
                                //    history.TOTALCARBON = history.KWH * carbonRate;
                                //}

                                //今日減碳量( 今日發電量 * (0.554/1000)[抓資料庫值]
                                //calcPowerStation.Today_Carbon = history.TODAYCARBON;
                                calcPowerStation.Today_Carbon = history.TodayKWh * carbonRate;

                                //總減碳量(總發電量 * (0.554/1000)[抓資料庫值]
                                //calcPowerStation.Total_Carbon = history.TotalKWH * carbonRate;
                                calcPowerStation.Total_Carbon = history.TotalKWH * carbonRate;

                                #endregion

                                #region 發電時間
                                calcPowerStation.SolarHour = history.SolarHour;
                                #endregion
                                #endregion

                                powerStationHistoriesHour.Add(history);

                                logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime);
                            }
                        }
                        #endregion

                        #region  step2-2. 取得該電站的當前這小時的設備歷史資料
                        var sensoravg_table_name = String.Format("s{1}01_sensoravg", powerStation.SiteDB, powerStation.Code);
                        var full_sensoravg_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, sensoravg_table_name);
                        var sensoravg_table_exist = await powerStationRepository.ExistTable(powerStation.SiteDB, sensoravg_table_name);
                        if (string.IsNullOrEmpty(sensoravg_table_exist))
                        {
                            logger.LogError($"【CalcPowerStationJob】【查無電站[{powerStation.Code}]的s{powerStation.Code}01_sensoravg資料表】");
                        }
                        else
                        {
                            logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的設備資訊】", powerStation.Code, dateTime);
                            PyrheliometerHistory sensorHistory = new PyrheliometerHistory();
                            sensorHistory.PowerStationId = powerStation.Id;
                            sensorHistory.Timestamp = Convert.ToDateTime(dateTime + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");

                            //1. 計算該電站sensor平均值 - 日照計(PYR)
                            try
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的日照計設備資訊】", powerStation.Code, dateTime);
                                var deviceInfos = await powerStationRepository.GetListPyrheliometerByPowerStationId(powerStation.Id, powerStation.SiteDB);
                                logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的日照計設備資訊】", powerStation.Code, dateTime);
                                logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的日照計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(deviceInfos));

                                if (deviceInfos != null && deviceInfos.Count() > 0)
                                {
                                    logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime);
                                    var pyrheliometerHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, deviceInfos, Convert.ToInt32(SensorTypeEnum.PYR));

                                    if (pyrheliometerHistory != null)
                                    {
                                        calcPowerStation.Today_irradiance = pyrheliometerHistory.Irradiance;

                                        sensorHistory.Irradiance = pyrheliometerHistory.Irradiance;

                                        //pyrheliometerHistory.Timestamp = Convert.ToDateTime(pyrheliometerHistory.Timestamp + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");
                                        //pyrheliometerHistory.PowerStationId = powerStation.Id;
                                        //pyrheliometerHistoriesHour.Add(pyrheliometerHistory);
                                    }
                                    logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime);
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime);
                                logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                            }

                            //2. 計算該電站sensor平均值 - 模組溫度計(MTR)
                            try
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的模組溫度計設備資訊】", powerStation.Code, dateTime);
                                var tempdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, "MTR", powerStation.SiteDB);
                                logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的模組溫度計設備資訊】", powerStation.Code, dateTime);
                                logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的模組溫度計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(tempdeviceInfos));
                                if (tempdeviceInfos != null && tempdeviceInfos.Count() > 0)
                                {
                                    logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的模組溫度計的平均值】", powerStation.Code, dateTime);
                                    var tempHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, tempdeviceInfos, Convert.ToInt32(SensorTypeEnum.MTR));
                                    if (tempHistory != null)
                                    {
                                        //tempHistory.Timestamp = Convert.ToDateTime(tempHistory.Timestamp + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");
                                        //tempHistory.PowerStationId = powerStation.Id;
                                        //TempHistoriesHour.Add(tempHistory);

                                        sensorHistory.Temperature = tempHistory.Temperature;

                                        logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的模組溫度計的平均值】", powerStation.Code, dateTime);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的模組溫度計的平均值】", powerStation.Code, dateTime);
                                logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                            }

                            //3. 計算該電站sensor平均值 - 環境溫度計(ETR)
                            try
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的環境溫度計設備資訊】", powerStation.Code, dateTime);
                                var ETRdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.ETR.ToString(), powerStation.SiteDB);
                                logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的環境溫度計設備資訊】", powerStation.Code, dateTime);
                                logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的環境溫度計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(ETRdeviceInfos));
                                if (ETRdeviceInfos != null && ETRdeviceInfos.Count() > 0)
                                {
                                    logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的環境溫度計的平均值】", powerStation.Code, dateTime);
                                    var ETRHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, ETRdeviceInfos, Convert.ToInt32(SensorTypeEnum.ETR));
                                    if (ETRHistory != null)
                                    {
                                        sensorHistory.EnvTemperature = ETRHistory.EnvTemperature;
                                        logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的環境溫度計的平均溫度】", powerStation.Code, dateTime);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的環境溫度計的平均值】", powerStation.Code, dateTime);
                                logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                            }

                            //4. 計算該電站 - 環境濕度計(EMM)
                            try
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的環境濕度計設備資訊】", powerStation.Code, dateTime);
                                var EMMdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.EMM.ToString(), powerStation.SiteDB);
                                logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的環境濕度計設備資訊】", powerStation.Code, dateTime);
                                logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的環境濕度計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(EMMdeviceInfos));
                                if (EMMdeviceInfos != null && EMMdeviceInfos.Count() > 0)
                                {
                                    logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的環境濕度計的平均值】", powerStation.Code, dateTime);
                                    var EMMHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, EMMdeviceInfos, Convert.ToInt32(SensorTypeEnum.EMM));
                                    if (EMMHistory != null)
                                    {
                                        sensorHistory.Humidity = EMMHistory.Humidity;
                                        logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的環境濕度計的平均值】", powerStation.Code, dateTime);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的環境濕度計的平均值】", powerStation.Code, dateTime);
                                logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                            }

                            //5. 計算該電站 - 風速計(VAN)
                            try
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的風速計設備資訊】", powerStation.Code, dateTime);
                                var VANdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.VAN.ToString(), powerStation.SiteDB);
                                logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的風速計設備資訊】", powerStation.Code, dateTime);
                                logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的風速計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(VANdeviceInfos));
                                if (VANdeviceInfos != null && VANdeviceInfos.Count() > 0)
                                {
                                    logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的風速計的平均值】", powerStation.Code, dateTime);
                                    var VANHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, VANdeviceInfos, Convert.ToInt32(SensorTypeEnum.VAN));
                                    if (VANHistory != null)
                                    {
                                        sensorHistory.Vane = VANHistory.Vane;
                                        logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的風速計的平均值】", powerStation.Code, dateTime);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的風速計的平均值】", powerStation.Code, dateTime);
                                logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                            }

                            //5. 計算該電站 - 落塵計(FOM)
                            try
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的落塵計設備資訊】", powerStation.Code, dateTime);
                                var FOMdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.FOM.ToString(), powerStation.SiteDB);
                                logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的落塵計設備資訊】", powerStation.Code, dateTime);
                                logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的落塵計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(FOMdeviceInfos));
                                if (FOMdeviceInfos != null && FOMdeviceInfos.Count() > 0)
                                {
                                    logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的落塵計的平均%】", powerStation.Code, dateTime);
                                    var FOMHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, FOMdeviceInfos, Convert.ToInt32(SensorTypeEnum.FOM));
                                    if (FOMHistory != null)
                                    {
                                        sensorHistory.Dust = FOMHistory.Dust;
                                        logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的落塵計的平均值】", powerStation.Code, dateTime);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的落塵計的平均值】", powerStation.Code, dateTime);
                                logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                            }

                            sensorHistoriesHour.Add(sensorHistory);
                        }

                        calcPowerStations.Add(calcPowerStation);
                        #endregion

                        #region step2-3. 計算該電站所有逆變器每小時值

                        var inverter_table_name = String.Format("s{0}01_inv", powerStation.Code);
                        var full_inverter_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, inverter_table_name);
                        var inverter_exist = await powerStationRepository.ExistTable(powerStation.SiteDB, inverter_table_name);
                        if (string.IsNullOrEmpty(inverter_exist))
                        {
                            logger.LogError("【CalcPowerStationJob】【查無電站[0]的s{0}01_inv資料表】", powerStation.Code);
                        }
                        else
                        {
                            try
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的逆變器設備資訊】", powerStation.Code, dateTime);
                                var controllers = await powerStationRepository.GetAllDeviceControllerId(powerStation.Id, powerStation.SiteDB);
                                var inverters = await powerStationRepository.InverterTable(controllers, powerStation.SiteDB);
                                var inverterIds = inverters.Where(x => x.Enabled == 1 && x.Status != 0).Select(x => x.InverterId).ToList();
                                logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的逆變器設備資訊】", powerStation.Code, dateTime);
                                logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的逆變器設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(inverterIds));

                                if (inverterIds != null && inverterIds.Count() > 0)
                                {
                                    logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime);
                                    var inverterHistories = await powerStationRepository.CalcInverterHisyortHourData(dateTime, powerStation.SiteDB, full_inverter_table_name, inverterIds);
                                    //取得日照計要找的欄位資訊
                                    var pyrheliometer = await powerStationRepository.GetFirstPyrheliometerInfo(powerStation.Id, powerStation.SiteDB);
                                    var pyrheliometerValue = await powerStationRepository.GetFirstPyrheliometerValue(dateTime, pyrheliometer.DBName, pyrheliometer.TableName, pyrheliometer.ColName);
                                    foreach (var inverterHistory in inverterHistories)
                                    {
                                        inverterHistory.Irradiance = pyrheliometerValue;
                                        inverterHistory.DC1KW = inverterHistory.DC1W / 1000;
                                        inverterHistory.DC2KW = inverterHistory.DC2W / 1000;
                                        inverterHistory.DC3KW = inverterHistory.DC3W / 1000;
                                        inverterHistory.DC4KW = inverterHistory.DC4W / 1000;
                                        inverterHistory.DC5KW = inverterHistory.DC5W / 1000;

                                        inverterHistory.DCKW = (inverterHistory.DC1W + inverterHistory.DC2W + inverterHistory.DC3W + inverterHistory.DC4W + inverterHistory.DC5W) / 1000;
                                        inverterHistory.ACKW = (inverterHistory.AC1W + inverterHistory.AC2W + inverterHistory.AC3W) / 1000;

                                        inverterHistory.TIMESTAMP = Convert.ToDateTime(inverterHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");
                                        inverterHistory.PowerStationId = powerStation.Id;

                                        inverterHistoriesHour.Add(inverterHistory);
                                    }
                                    logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime);
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime);
                                logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                            }
                        }
                        #endregion

                        #region step2-4. 計算該電站所有sensoravg
                        try
                        {

                            //var seneoravg_table_name = String.Format("s{0}01_sensoravg", powerStation.Code);
                            //var full_seneoravg_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, seneoravg_table_name);
                            //var exist_seneoravg_table = await powerStationRepository.ExistTable(powerStation.SiteDB, seneoravg_table_name);

                            if (!string.IsNullOrEmpty(sensoravg_table_exist))
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime);
                                var sensorAvgHistory = await powerStationRepository.CalcSensorAvgHistory(dateTime, full_sensoravg_table_name);
                                logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime);

                                if (sensorAvgHistory != null)
                                {
                                    sensorAvgHistory.PowerStationId = powerStation.Id;
                                    sensorAvgHistory.TIMESTAMP = Convert.ToDateTime(sensorAvgHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");

                                    sensorAvgHistoryHour.Add(sensorAvgHistory);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime);
                            logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                        }
                        #endregion

                        #region step2-5. 計算該電站meter
                        try
                        {
                            var meter_table_name = String.Format("s{0}01_meter", powerStation.Code);
                            var full_meter_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, meter_table_name);
                            var exist_meter_table = await powerStationRepository.ExistTable(powerStation.SiteDB, meter_table_name);
                            if (string.IsNullOrEmpty(exist_meter_table))
                            {
                                logger.LogError($"【CalcPowerStationJob】【查無電站[{powerStation.Code}]的s{powerStation.Code}01_meter資料表】");
                            }
                            else
                            {
                                logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime);
                                var meterHistory = await powerStationRepository.CalcMeterHistory(dateTime, full_meter_table_name);
                                logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime);

                                if (meterHistory != null)
                                {
                                    meterHistory.PowerStationId = powerStation.Id;
                                    meterHistory.TIMESTAMP = Convert.ToDateTime(meterHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");

                                    meterHistoriesHour.Add(meterHistory);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime);
                            logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                        }
                        #endregion

                        #region 確認是否有觀測站(沒有則新增)
                        try
                        {
                            if (powerStation.WeathersStationId == null)
                            {
                                var weatherStationId = "";
                                double shortLocation = 9999;
                                foreach (var Location in observation.Records.Location)
                                {

                                    if (powerStation.Coordinate != null)
                                    {
                                        var powerLocation = powerStation.Coordinate.Split(',');
                                        var nowLocation = Math.Sqrt(Math.Pow(Convert.ToDouble(powerLocation[0]) - Convert.ToDouble(Location.Lat), 2) + Math.Pow(Convert.ToDouble(powerLocation[1]) - Convert.ToDouble(Location.Lon), 2));
                                        if (nowLocation < shortLocation)
                                        {
                                            shortLocation = nowLocation;
                                            weatherStationId = Location.StationId;
                                            calcPowerStation.TodayWeatherTemp = Convert.ToDouble(Location.WeatherElement[0].ElementValue);
                                        }
                                    }
                                }

                                calcPowerStation.WeathersStationId = weatherStationId;
                            }

                            WeatherObservation weatherObservation = new WeatherObservation();
                            if (powerStation.WeathersStationId != null && observation != null)
                            {
                                foreach (var Location in observation.Records.Location)
                                {
                                    if (Location.StationId == powerStation.WeathersStationId)
                                    {
                                        calcPowerStation.TodayWeatherTemp = Convert.ToDouble(Location.WeatherElement[0].ElementValue);
                                        weatherObservation.PowerStationId = powerStation.Id;
                                        weatherObservation.Temp = Convert.ToDouble(Location.WeatherElement[0].ElementValue);
                                        weatherObservation.ObsTime = !string.IsNullOrEmpty(Location.Time.ObsTime) ? Convert.ToInt32(Location.Time.ObsTime.Substring(0, 4)) >= 1971 ? Location.Time.ObsTime : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                        calcPowerStation.WeathersStationId = powerStation.WeathersStationId;
                                        break;
                                    }
                                }
                                weatherObservations.Add(weatherObservation);
                            }

                            logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime);
                            var weather = await powerStationRepository.SelectNowWeather(powerStation.CityId);
                            logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime);
                            if (weather != null)
                            {
                                calcPowerStation.TodayWeather = weather.WeatherKey;
                                calcPowerStation.RateOfRain = weather.PoP;
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.LogError("【CalcPowerStationJob】【取得失敗電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime);
                            logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message);
                        }
                        #endregion
                    }
                    catch (Exception exception)
                    {
                        logger.LogError("【{0}】{1}", "CalcPowerStationJob", exception.Message);
                    }
                }
                #endregion

                if (!this.environment.IsDevelopment())
                {
                    #region step3. 將historiers INSERT 到 power_station_history_hour 資料表
                    List<string> history_properties = new List<string>()
                    {
                        "PowerStationId",
                        "TIMESTAMP",
                        "SITEID",
                        "SITETYPE",
                        "KWH",
                        "TODAYKWH",
                        "TOTALKWH",
                        "KWHKWP",
                        "PR",
                        "MP",
                        "SolarHour",
                        "MONEY",
                        "CARBON",
                        "TODAYMONEY",
                        "TOTALMONEY",
                        "TODAYCARBON",
                        "TOTALCARBON"
                    };

                    await powerStationRepository.AddPowerStationHistory(powerStationHistoriesHour, history_properties);
                    #endregion

                    #region step4. 將sensor History INSERT 到 sensor_history_hour 資料表
                    List<string> sensor_history_properties = new List<string>()
                    {
                        "PowerStationId",
                        "TIMESTAMP",
                        "Irradiance",
                        "Temperature",
                        "EnvTemperature",
                        "Humidity",
                        "Vane",
                        "Dust"
                    };

                    await powerStationRepository.AddSensorHistoryHour(sensorHistoriesHour, sensor_history_properties);

                    //List<string> Temp_history_properties = new List<string>()
                    //{
                    //    "PowerStationId",
                    //    "TIMESTAMP",
                    //    "Temperature"
                    //};

                    //await powerStationRepository.AddTempHistory(TempHistoriesHour, Temp_history_properties);
                    #endregion

                    #region step5. calcPowerStations UPDATE 到 power_station 資料表
                    List<string> power_station_properties = new List<string>()
                    {
                        "Id",
                        "kwh",
                        "Today_kwh",
                        "Total_kwh",
                        "today_kwhkwp",
                        "today_money",
                        "total_money",
                        "today_PR",
                        "today_carbon",
                        "total_carbon",
                        "today_irradiance",
                        "SolarHour",
                        "WeathersStationId",
                        "TodayWeatherTemp",
                        "TodayWeather",
                        "RateOfRain"
                    };

                    await powerStationRepository.UpdateList(calcPowerStations, power_station_properties);
                    #endregion

                    #region step6. 將 inverter INSERT 到 inverter_history_hour 資料表
                    List<string> inverter_history_properties = new List<string>()
                    {
                        "PowerStationId",
                        "INVERTERID",
                        "TIMESTAMP",
                        "Irradiance",
                        "AC1V",
                        "AC1A",
                        "AC1W",
                        "AC1F",
                        "AC1WH",
                        "AC2V",
                        "AC2A",
                        "AC2W",
                        "AC2F",
                        "AC2WH",
                        "AC3V",
                        "AC3A",
                        "AC3W",
                        "AC3F",
                        "AC3WH",
                        "DC1V",
                        "DC1A",
                        "DC1W",
                        "DC1KW",
                        "DC1WH",
                        "DC2V",
                        "DC2A",
                        "DC2W",
                        "DC2KW",
                        "DC2WH",
                        "DC3V",
                        "DC3A",
                        "DC3W",
                        "DC3KW",
                        "DC3WH",
                        "DC4V",
                        "DC4A",
                        "DC4W",
                        "DC4KW",
                        "DC4WH",
                        "DC5V",
                        "DC5A",
                        "DC5W",
                        "DC5KW",
                        "DC5WH",
                        "PR",
                        "RA1",
                        "RA2",
                        "RA3",
                        "RA4",
                        "RA5",
                        "DCKW",
                        "ACKW",
                        "KWH",
                        "TODAYKWH",
                        "TOTALKWH",
                        "KWHKWP",
                    };

                    await powerStationRepository.AddInverterHistory(inverterHistoriesHour, inverter_history_properties);
                    #endregion

                    #region step7. 將 sensoravg INSERT 到 sensoravg_history_hour 資料表
                    List<string> sensoravg_history_properties = new List<string>()
                    {
                        "PowerStationId",
                        "TIMESTAMP",
                        "SENSORAVG01",
                        "SENSORAVG02",
                        "SENSORAVG03",
                        "SENSORAVG04",
                        "SENSORAVG05",
                        "SENSORAVG06",
                        "SENSORAVG07",
                        "SENSORAVG08",
                        "SENSORAVG09",
                        "SENSORAVG10",
                        "SENSORAVG11",
                        "SENSORAVG12",
                        "SENSORAVG13",
                        "SENSORAVG14",
                        "SENSORAVG15",
                        "SENSORAVG16",
                        "SENSORAVG17",
                        "SENSORAVG18",
                        "SENSORAVG19",
                        "SENSORAVG20",
                        "SENSORAVG21",
                        "SENSORAVG22",
                        "SENSORAVG23",
                        "SENSORAVG24",
                        "SENSORAVG25",
                        "SENSORAVG26",
                        "SENSORAVG27",
                        "SENSORAVG28",
                        "SENSORAVG29",
                        "SENSORAVG30",
                        "SENSORAVG31",
                        "SENSORAVG32",
                        "SENSORAVG33",
                        "SENSORAVG34",
                        "SENSORAVG35",
                        "SENSORAVG36",
                        "SENSORAVG37",
                        "SENSORAVG38",
                        "SENSORAVG39",
                        "SENSORAVG40",
                        "SENSORAVG41",
                        "SENSORAVG42",
                        "SENSORAVG43",
                        "SENSORAVG44",
                        "SENSORAVG45",
                        "SENSORAVG46",
                        "SENSORAVG47",
                        "SENSORAVG48",
                        "SENSORAVG49",
                        "SENSORAVG50",
                    };

                    await powerStationRepository.AddSensorAvgHistory(sensorAvgHistoryHour, sensoravg_history_properties);
                    #endregion

                    #region step8. 將 meter INSERT 到 meter_history_hour 資料表
                    List<string> memter_history_properties = new List<string>()
                    {
                        "PowerStationId",
                        "TIMESTAMP",
                        "METERID",
                        "V_AB",
                        "V_BC",
                        "V_CA",
                        "I_A",
                        "I_B",
                        "I_C",
                        "I_C",
                        "P",
                        "F",
                        "INPUT_KWH",
                        "OUTPUT_KWH"
                    };

                    await powerStationRepository.AddMeterHistory(meterHistoriesHour, memter_history_properties);
                    #endregion

                    #region step9. 新增天氣資訊
                    List<string> weather_observation_properties = new List<string>()
                    {
                        "PowerStationId",
                        "ObsTime",
                        "Temp"
                    };
                    await powerStationRepository.AddWeatherObservation(weatherObservations, weather_observation_properties);
                    #endregion
                }

                logger.LogInformation("【CalcPowerStationJob】【任務完成】");
            }
            catch (Exception exception)
            {
                logger.LogError("【CalcPowerStationJob】[Exception] - {0}", exception.Message);
                if (exception.InnerException != null)
                {
                    logger.LogError("【CalcPowerStationJob】[InnerException] - {0}", exception.InnerException.Message);
                }
            }
        }
    }
}
