using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using SolarPower.Models;
using SolarPower.Models.PowerStation;
using SolarPower.Models.Role;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SolarPower.Controllers
{
    public class AnalysisStationInfoController : MyBaseController<AnalysisStationInfoController>
    {
        private readonly IPowerStationRepository powerStationRepository;

        public AnalysisStationInfoController(IPowerStationRepository powerStationRepository) : base()
        {
            this.powerStationRepository = powerStationRepository;
        }

        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public async Task<ApiResult<Dictionary<string, Dictionary<string, List<PowerStationDevice>>>>> GetDeviceCollapse(string filter)
        {
            ApiResult<Dictionary<string, Dictionary<string, List<PowerStationDevice>>>> apiResult = new ApiResult<Dictionary<string, Dictionary<string, List<PowerStationDevice>>>>();
            try
            {
                var powerStations = new List<PowerStation>();

                powerStations = myPowerStationService.GetMyPowerStations(myUser);

                var siteDBNamePowerStationId = new Dictionary<string, List<int>>();

                var powerStation_siteDB_Group = powerStations.GroupBy(x => x.SiteDB).ToList();
                foreach (var siteDB_Group in powerStation_siteDB_Group)
                {
                    var powerStationIds = siteDB_Group.Select(x => x.Id).ToList();
                    siteDBNamePowerStationId.Add(siteDB_Group.Key, powerStationIds);
                }

                var powerStationDevices = await powerStationRepository.GetPowerStationDevice(siteDBNamePowerStationId, filter);

                //powerStationDevices = powerStationDevices.Where(x => x.DeviceId != null).ToList();

                var powerStationDevice_cityName_Group = powerStationDevices.GroupBy(x => x.CityName).ToList();

                var deviceCollapse = new Dictionary<string, Dictionary<string, List<PowerStationDevice>>>();
                foreach (var cityName_Group in powerStationDevice_cityName_Group)
                {
                    var device_psName_Group = cityName_Group.GroupBy(x => x.PowerStationName).ToList();

                    var deviceDic = new Dictionary<string, List<PowerStationDevice>>();

                    foreach (var psName_Group in device_psName_Group)
                    {
                        //電站總覽
                        PowerStationDevice powerStation = new PowerStationDevice()
                        {
                            CityName = cityName_Group.Key,
                            PowerStationName = psName_Group.Key,
                            PowerStationId = psName_Group.First().PowerStationId,
                            DeviceName = "電站總覽",
                            DeviceType = "PWS",
                            DeviceId = psName_Group.First().PowerStationId.ToString()
                        };

                        var temp = new List<PowerStationDevice>();
                        temp.Add(powerStation);
                        foreach (var device in psName_Group)
                        {
                            if(!string.IsNullOrEmpty(device.DeviceId))
                            {
                                temp.Add(device);
                            }
                        }
                        deviceDic.Add(psName_Group.Key, temp);
                    }

                    deviceCollapse.Add(cityName_Group.Key, deviceDic);
                }

                apiResult.Code = "0000";

                apiResult.Data = deviceCollapse;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                Logger.LogError("【" + controllerName + "/" + actionName + "】");
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<AnalysisDevice>> GetAnalysisByDeviceIds(PostAnalysisStation post)
        {
            ApiResult<AnalysisDevice> apiResult = new ApiResult<AnalysisDevice>();
            try
            {
                AnalysisDevice analysisDevice = new AnalysisDevice();
                analysisDevice.Series = new List<DeviceHistoryInfo>();

                //先將欲查詢的設備找出設備的資料庫欄位
                var device_powerStationId_Group = post.DeviceIdInfos.GroupBy(x => x.PowerStationId).ToList();
                Dictionary<int, List<Device>> deviceDic = new Dictionary<int, List<Device>>();
                List<StationIdWithMeterIds> meterDic = new List<StationIdWithMeterIds>();
                List<int> selected_powerStationIds = new List<int>();
                foreach (var psId_Group in device_powerStationId_Group)
                {
                    var powerStation = await powerStationRepository.GetOneAsync(psId_Group.Key);

                    //區分電站總覽or設備
                    var temp_psIds = psId_Group.Where(x => x.DeviceType == "PWS").Select(x => Convert.ToInt32(x.DeviceId)).ToList();
                    if(temp_psIds.Count() > 0)
                    {
                        selected_powerStationIds.AddRange(temp_psIds);
                    }
                    var selected_meter = psId_Group.Where(x => x.DeviceType == "PWR").Select(x => x.DeviceId).ToList();
                    var selected_device = psId_Group.Where(x => x.DeviceType != "PWS" && x.DeviceType != "PWR").Select(x => x.DeviceId).ToList();

                    var temp_meter = await powerStationRepository.GetDeviceByPowerStationIdAndDeviceIds(powerStation.SiteDB, powerStation.Id, selected_meter);
                    if (temp_meter.Count() > 0)
                    {
                        StationIdWithMeterIds stationIdWithMeterIds = new StationIdWithMeterIds();
                        stationIdWithMeterIds.PowerStationId = psId_Group.Key;
                        stationIdWithMeterIds.MeterIds = temp_meter.Select(x => x.UID).ToList();

                        meterDic.Add(stationIdWithMeterIds);
                    }

                    var temp_device = await powerStationRepository.GetDeviceByPowerStationIdAndDeviceIds(powerStation.SiteDB, powerStation.Id, selected_device);
                    if (temp_device.Count() > 0)
                    {
                        deviceDic.Add(psId_Group.Key, temp_device);
                    }
                }

                analysisDevice.MultipleYaxes = new Dictionary<string, string>()
                {
                    { "KWH", "發電量"},
                    { "Irradiance", "日照度"},
                    { "KWHKWP", "發電小時"},
                    { "PR", "PR %"},
                    { "SolarHour", "日照小時"},
                    { "Temperature", "模組溫度"},
                    { "EnvTemperature", "環境溫度計"},
                    { "Humidity", "濕度"},
                    { "Vane", "風速"},
                    { "Dust", "落塵%"},
                    { "OUTPUT_KWH", "輸出發電量(kWh)"},
                    { "INPUT_KWH", "輸入發電量(kWh)"},
                    { "V_AB", "電壓 AB(V)"},
                    { "V_BC", "電壓 BC(V)"},
                    { "V_CA", "電壓 CA(V)"},
                    { "I_A", "電流 A(A)"},
                    { "I_B", "電流 B(A)"},
                    { "I_C", "電流 C(A)"},
                    { "P", "有效功率(kW)"},
                    { "F", "頻率(Hz)"},
                };

                var XAxis = new List<string>();

                #region 電站資料
                if (selected_powerStationIds.Count() > 0)
                {
                    var powerStationHistories = await powerStationRepository.GetPowerStationHistory(post.SelectedDate, post.SearchType, selected_powerStationIds);

                    XAxis.AddRange(powerStationHistories.Select(x => x.Timestamp).Distinct().ToList());

                    var powerStationHistories_Id_Group = powerStationHistories.GroupBy(x => x.PowerStationId).ToList();

                    foreach (var item in powerStationHistories_Id_Group)
                    {
                        var powerStation = await powerStationRepository.GetOneAsync(item.Key);

                        var temp_item = item.OrderBy(x => x.Timestamp).ToList();

                        DeviceHistoryInfo Irradiance = new DeviceHistoryInfo();
                        Irradiance.Name = string.Format("{0}:{1}", powerStation.Name, analysisDevice.MultipleYaxes["Irradiance"]);
                        Irradiance.YaxesKey = "Irradiance";
                        Irradiance.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.Timestamp) > -1)
                            {
                                Irradiance.Values.Add(history.Irradiance);
                            }
                            else
                            {
                                Irradiance.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(Irradiance);

                        DeviceHistoryInfo KWH = new DeviceHistoryInfo();
                        KWH.Name = string.Format("{0}:{1}", powerStation.Name, analysisDevice.MultipleYaxes["KWH"]);
                        KWH.YaxesKey = "KWH";
                        KWH.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.Timestamp) > -1)
                            {
                                KWH.Values.Add(Math.Round(history.KWH, 2));
                            }
                            else
                            {
                                KWH.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(KWH);

                        DeviceHistoryInfo solarHour = new DeviceHistoryInfo();
                        solarHour.Name = string.Format("{0}:{1}", powerStation.Name, analysisDevice.MultipleYaxes["SolarHour"]);
                        solarHour.YaxesKey = "SolarHour";
                        solarHour.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.Timestamp) > -1)
                            {
                                solarHour.Values.Add(Math.Round(history.SolarHour, 2));
                            }
                            else
                            {
                                solarHour.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(solarHour);

                        DeviceHistoryInfo KWHKWP = new DeviceHistoryInfo();
                        KWHKWP.Name = string.Format("{0}:{1}", powerStation.Name, analysisDevice.MultipleYaxes["KWHKWP"]);
                        KWHKWP.YaxesKey = "KWHKWP";
                        KWHKWP.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.Timestamp) > -1)
                            {
                                KWHKWP.Values.Add(Math.Round(history.KWHKWP, 2));
                            }
                            else
                            {
                                KWHKWP.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(KWHKWP);

                        DeviceHistoryInfo PR = new DeviceHistoryInfo();
                        PR.Name = string.Format("{0}:{1}", powerStation.Name, analysisDevice.MultipleYaxes["PR"]);
                        PR.YaxesKey = "PR";
                        PR.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.Timestamp) > -1)
                            {
                                PR.Values.Add(Math.Round(history.PR, 2));
                            }
                            else
                            {
                                PR.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(PR);

                        DeviceHistoryInfo modelTemperature = new DeviceHistoryInfo();
                        modelTemperature.Name = string.Format("{0}:{1}", powerStation.Name, analysisDevice.MultipleYaxes["Temperature"]);
                        modelTemperature.YaxesKey = "Temperature";
                        modelTemperature.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.Timestamp) > -1)
                            {
                                modelTemperature.Values.Add(Math.Round(history.Temperature, 2));
                            }
                            else
                            {
                                modelTemperature.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(modelTemperature);
                    }
                }
                #endregion

                #region 電錶資料
                if (meterDic.Count() > 0)
                {
                    var meterHistories = await powerStationRepository.GetMeterHistory(post.SelectedDate, post.SearchType, meterDic);

                    XAxis.AddRange(meterHistories.Select(x => x.TIMESTAMP).Distinct().ToList());

                    var meterHistories_Id_Group = meterHistories.GroupBy(x => x.METERID).ToList();

                    foreach (var item in meterHistories_Id_Group)
                    {
                        var temp_item = item.OrderBy(x => x.TIMESTAMP).ToList();

                        DeviceHistoryInfo OUTPUT_KWH = new DeviceHistoryInfo();
                        OUTPUT_KWH.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["OUTPUT_KWH"]);
                        OUTPUT_KWH.YaxesKey = "OUTPUT_KWH";
                        OUTPUT_KWH.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                OUTPUT_KWH.Values.Add(Math.Round(history.OUTPUT_KWH, 2));
                            }
                            else
                            {
                                OUTPUT_KWH.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(OUTPUT_KWH);

                        DeviceHistoryInfo INPUT_KWH = new DeviceHistoryInfo();
                        INPUT_KWH.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["INPUT_KWH"]);
                        INPUT_KWH.YaxesKey = "INPUT_KWH";
                        INPUT_KWH.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                INPUT_KWH.Values.Add(Math.Round(history.INPUT_KWH, 2));
                            }
                            else
                            {
                                INPUT_KWH.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(INPUT_KWH);

                        DeviceHistoryInfo V_AB = new DeviceHistoryInfo();
                        V_AB.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["V_AB"]);
                        V_AB.YaxesKey = "V_AB";
                        V_AB.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                V_AB.Values.Add(Math.Round(history.V_AB, 2));
                            }
                            else
                            {
                                V_AB.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(V_AB);

                        DeviceHistoryInfo V_BC = new DeviceHistoryInfo();
                        V_BC.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["V_BC"]);
                        V_BC.YaxesKey = "V_BC";
                        V_BC.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                V_BC.Values.Add(Math.Round(history.V_BC, 2));
                            }
                            else
                            {
                                V_BC.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(V_BC);

                        DeviceHistoryInfo V_CA = new DeviceHistoryInfo();
                        V_CA.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["V_BC"]);
                        V_CA.YaxesKey = "V_CA";
                        V_CA.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                V_CA.Values.Add(Math.Round(history.V_CA, 2));
                            }
                            else
                            {
                                V_CA.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(V_CA);

                        DeviceHistoryInfo I_A = new DeviceHistoryInfo();
                        I_A.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["I_A"]);
                        I_A.YaxesKey = "I_A";
                        I_A.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                I_A.Values.Add(Math.Round(history.I_A, 2));
                            }
                            else
                            {
                                I_A.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(I_A);

                        DeviceHistoryInfo I_B = new DeviceHistoryInfo();
                        I_B.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["I_B"]);
                        I_B.YaxesKey = "I_B";
                        I_B.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                I_B.Values.Add(Math.Round(history.I_B, 2));
                            }
                            else
                            {
                                I_B.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(I_B);

                        DeviceHistoryInfo I_C = new DeviceHistoryInfo();
                        I_C.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["I_C"]);
                        I_C.YaxesKey = "I_C";
                        I_C.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                I_C.Values.Add(Math.Round(history.I_C, 2));
                            }
                            else
                            {
                                I_C.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(I_C);

                        DeviceHistoryInfo P = new DeviceHistoryInfo();
                        P.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["P"]);
                        P.YaxesKey = "P";
                        P.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                P.Values.Add(Math.Round(history.P, 2));
                            }
                            else
                            {
                                P.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(P);

                        DeviceHistoryInfo F = new DeviceHistoryInfo();
                        F.Name = string.Format("{0}:{1}", item.Key, analysisDevice.MultipleYaxes["F"]);
                        F.YaxesKey = "F";
                        F.Values = new List<double>();
                        foreach (var history in temp_item)
                        {
                            if (XAxis.IndexOf(history.TIMESTAMP) > -1)
                            {
                                F.Values.Add(Math.Round(history.F, 2));
                            }
                            else
                            {
                                F.Values.Add(0);
                            }
                        }
                        analysisDevice.Series.Add(F);
                    }
                }


                #endregion

                #region 設備資料
                foreach (var devices in deviceDic)
                {
                    var result = await powerStationRepository.GetSensorAvgByDevices(post.SelectedDate, post.SearchType, devices.Value);

                    foreach (var rows in result)
                    {
                        var fields = rows as IDictionary<string, object>;
                        XAxis.Add(fields["TIMESTAMP"].ToString());
                    }


                    foreach (var device in devices.Value)
                    {
                        DeviceHistoryInfo deviceHistoryInfo = new DeviceHistoryInfo();
                        var suffix = "";
                        var YaxesKey = "";
                        switch (device.Type)
                        {
                            case "PYR": //日照計
                                suffix = analysisDevice.MultipleYaxes["Irradiance"];
                                YaxesKey = "Irradiance";
                                break;
                            case "ETR": //環境溫度計
                                suffix = analysisDevice.MultipleYaxes["EnvTemperature"];
                                YaxesKey = "EnvTemperature";
                                break;
                            case "MTR": //模組溫度計
                                suffix = analysisDevice.MultipleYaxes["Temperature"];
                                YaxesKey = "Temperature";
                                break;
                            case "VAN": //風速計
                                suffix = analysisDevice.MultipleYaxes["Vane"];
                                YaxesKey = "Vane";
                                break;
                            case "FOM": //落塵計
                                suffix = analysisDevice.MultipleYaxes["Dust"];
                                YaxesKey = "Dust";
                                break;
                            case "EMM": //環境濕度計
                                suffix = analysisDevice.MultipleYaxes["Humidity"];
                                YaxesKey = "Humidity";
                                break;
                            default:
                                suffix = string.Empty;
                                break;
                        }
                        deviceHistoryInfo.Name = string.Format("{0}:{1}", device.Name, suffix);
                        deviceHistoryInfo.YaxesKey = YaxesKey;
                        deviceHistoryInfo.Values = new List<double>();
                        foreach (var rows in result)
                        {
                            var fields = rows as IDictionary<string, object>;
                            if (XAxis.IndexOf(fields["TIMESTAMP"].ToString()) > -1)
                            {
                                deviceHistoryInfo.Values.Add(Math.Round(Convert.ToDouble(fields[device.UID]), 2));
                            }
                            else
                            {
                                deviceHistoryInfo.Values.Add(0);
                            }
                        }

                        analysisDevice.Series.Add(deviceHistoryInfo);
                    }
                }
                #endregion

                analysisDevice.XAxis = XAxis.Distinct().ToList();

                apiResult.Code = "0000";

                apiResult.Data = analysisDevice;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                Logger.LogError("【" + controllerName + "/" + actionName + "】");
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            return apiResult;
        }
    }
}
