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

namespace SolarPower.Controllers
{
    public class StationOverviewController : MyBaseController<StationOverviewController>
    {
        private readonly IOverviewRepository overviewRepository;
        private readonly IPowerStationRepository powerStationRepository;
        private string stationImageFilePath = "/upload/power_station/";
        public StationOverviewController(
            IOverviewRepository overviewRepository,
            IPowerStationRepository powerStationRepository) : base()
        {
            this.overviewRepository = overviewRepository;
            this.powerStationRepository = powerStationRepository;
        }

        public IActionResult Index()
        {
            return View();
        }
        public IActionResult Info()
        {
            return View("~/Views/StationOverview/StationOverviewInfo.cshtml");
        }

        /// <summary>
        /// 取得該使用者可看的所有電站分佈縣市以及各縣市電站數量
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<PowerStation>>> GetSolarByCity(UseStatusCityGetPowerStation post)
        {
            ApiResult<List<PowerStation>> apiResult = new ApiResult<List<PowerStation>>();
            List<PowerStation> solaramount = new List<PowerStation>();
            try
            {
                apiResult.Code = "0000";
                solaramount = await overviewRepository.GetSolarByCity(myUser, post);

                foreach (var solar in solaramount)
                {
                    solar.MainDisplay = Path.Combine(stationImageFilePath, solar.Id.ToString()) + "/" + solar.MainDisplay;
                }

                apiResult.Data = solaramount;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = exception.ToString();
            }

            return apiResult;
        }

        [HttpPost]
        public ApiResult<List<MyPowerStationSummary>> GetPowerStationCollapse(string filter)
        {
            ApiResult<List<MyPowerStationSummary>> apiResult = new ApiResult<List<MyPowerStationSummary>>();
            try
            {
                apiResult.Code = "0000";
                var powerStationSummary = powerStationRepository.GetMyPowerStationSummary(myUser, filter);

                apiResult.Data = powerStationSummary;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = exception.ToString();
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<MapOverview>> GetStationCard(StationIds post)
        {
            ApiResult<MapOverview> apiResult = new ApiResult<MapOverview>();

            MapOverview mapOverview = new MapOverview();
            try
            {
                var overview = await overviewRepository.GetOverviewByPowerStationIds(post.Ids);
                mapOverview.Today_kwh = overview.Today_kwh;
                mapOverview.Total_kwh = overview.Total_kwh;
                mapOverview.Today_irradiance = overview.Today_irradiance;
                mapOverview.Avg_irradiance = overview.Avg_irradiance;
                mapOverview.Today_PR = overview.Today_PR;
                mapOverview.Avg_PR = overview.Avg_PR;
                mapOverview.Today_kwhkwp = overview.Today_kwhkwp;
                mapOverview.Avg_kwhkwp = overview.Avg_kwhkwp;
                mapOverview.Today_carbon = overview.Today_carbon;
                mapOverview.Total_carbon = overview.Total_carbon;

                mapOverview.CapacityDataTables = await overviewRepository.GetCapacityDataTableByPowerStationIds(post.Ids);

                var totalPowerStationCount = 0;
                var totalCapacity = 0.0;

                foreach (var capacity in mapOverview.CapacityDataTables)
                {
                    totalPowerStationCount += capacity.SubPowerStationCount;
                    totalCapacity += capacity.SubTotalCapacity;
                }

                mapOverview.TotalPowerStationCount = totalPowerStationCount;
                mapOverview.TotalCapacity = totalCapacity;

                mapOverview.UpdatedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");


                apiResult.Code = "0000";
                apiResult.Data = mapOverview;

            }
            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<StationOverview>> GetOneStationUpToDateInfo(StationIds post)
        {
            ApiResult<StationOverview> apiResult = new ApiResult<StationOverview>();

            StationOverview stationOverview = new StationOverview();
            try
            {
                var overview = await overviewRepository.GetOverviewByPowerStationIds(post.Ids);
                stationOverview.Today_kwh = overview.Today_kwh;
                stationOverview.Total_kwh = overview.Total_kwh;
                stationOverview.Today_irradiance = overview.Today_irradiance;
                stationOverview.Avg_irradiance = overview.Avg_irradiance;
                stationOverview.Today_PR = overview.Today_PR;
                stationOverview.Avg_PR = overview.Avg_PR;
                stationOverview.Today_kwhkwp = overview.Today_kwhkwp;
                stationOverview.Avg_kwhkwp = overview.Avg_kwhkwp;
                stationOverview.Today_money = overview.Today_money;
                stationOverview.Total_money = overview.Total_money;
                stationOverview.Today_carbon = overview.Today_carbon;
                stationOverview.Total_carbon = overview.Total_carbon;

                stationOverview.UpdatedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                if (myUser.Role.Auths.Contains("ShowMoney"))
                {
                    stationOverview.IsShowMoney = 1;
                }
                else
                {
                    stationOverview.IsShowMoney = 0;
                    stationOverview.Today_money = 0;
                    stationOverview.Total_money = 0;
                }

                var powerStation = await powerStationRepository.GetOneAsync(post.Ids.First());

                stationOverview.SolarType = powerStation.SolarType;
                stationOverview.CityName = powerStation.CityName;
                stationOverview.TodayWeather = powerStation.TodayWeather;
                stationOverview.TodayWeatherTemp = powerStation.TodayWeatherTemp;
                stationOverview.RateOfRain = powerStation.RateOfRain;
                stationOverview.StationName = powerStation.Name;
                apiResult.Code = "0000";
                apiResult.Data = stationOverview;

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

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

        public async Task<ApiResult<ChartUptoDate>> GetChartUpToDate(int id)
        {
            ApiResult<ChartUptoDate> apiResult = new ApiResult<ChartUptoDate>();

            ChartUptoDate chartUptoDate = new ChartUptoDate();

            try
            {
                var nowDay = DateTime.Now.ToString("yyyy-MM-dd");

                //今日發電量日照度List
                var powerIrradianceToday = await overviewRepository.GetListPowerIrradianceTodayByPowerStationId(id, nowDay);
                //今日資料轉換
                PowerIrradianceChart powerIrradianceTodayChart = new PowerIrradianceChart();
                powerIrradianceTodayChart.Labels = powerIrradianceToday.Select(x => x.Label).ToList();
                powerIrradianceTodayChart.PowerDatas = powerIrradianceToday.Select(x => x.PowerData).ToList();
                powerIrradianceTodayChart.IrradianceDatas = powerIrradianceToday.Select(x => x.IrradianceData).ToList();
                chartUptoDate.ChartToday = powerIrradianceTodayChart;

                //7日發電量日照度List
                var powerIrradiance7day = await overviewRepository.GetListPowerIrradiance7dayByPowerStationId(id, nowDay);
                //7日資料轉換
                PowerIrradianceChart powerIrradiance7dayChart = new PowerIrradianceChart();
                powerIrradiance7dayChart.Labels = powerIrradiance7day.Select(x => x.Label).ToList();
                powerIrradiance7dayChart.PowerDatas = powerIrradiance7day.Select(x => x.PowerData).ToList();
                powerIrradiance7dayChart.IrradianceDatas = powerIrradiance7day.Select(x => x.IrradianceData).ToList();
                chartUptoDate.Chart7day = powerIrradiance7dayChart;

                //本月發電量日照度List
                var powerIrradianceMonth = await overviewRepository.GetListPowerIrradianceMonthByPowerStationId(id, nowDay);
                //今日資料轉換
                PowerIrradianceChart powerIrradianceMonthChart = new PowerIrradianceChart();
                powerIrradianceMonthChart.Labels = powerIrradianceMonth.Select(x => x.Label).ToList();
                powerIrradianceMonthChart.PowerDatas = powerIrradianceMonth.Select(x => x.PowerData).ToList();
                powerIrradianceMonthChart.IrradianceDatas = powerIrradianceMonth.Select(x => x.IrradianceData).ToList();
                chartUptoDate.ChartMonth = powerIrradianceMonthChart;

                //本年發電量日照度List
                var powerIrradianceYear = await overviewRepository.GetListPowerIrradianceYearByPowerStationId(id, nowDay);
                //今日資料轉換
                PowerIrradianceChart powerIrradianceYearChart = new PowerIrradianceChart();
                powerIrradianceYearChart.Labels = powerIrradianceYear.Select(x => x.Label).ToList();
                powerIrradianceYearChart.PowerDatas = powerIrradianceYear.Select(x => x.PowerData).ToList();
                powerIrradianceYearChart.IrradianceDatas = powerIrradianceYear.Select(x => x.IrradianceData).ToList();
                chartUptoDate.ChartYear = powerIrradianceYearChart;

                apiResult.Code = "0000";
                apiResult.Data = chartUptoDate;

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

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

        public async Task<ApiResult<List<CheckBox>>> GetInverterCheckBox(int id)
        {
            ApiResult<List<CheckBox>> apiResult = new ApiResult<List<CheckBox>>();


            try
            {
                var powerStation = await powerStationRepository.GetOneAsync(id);

                if (powerStation == null)
                {
                    apiResult.Code = "9992";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                var invertCheckBoxes = await overviewRepository.GetInvertCheckBoxByPowerStationId(powerStation.Id, powerStation.SiteDB);

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

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

        public async Task<ApiResult<InverterHeatMap>> GetInverterHeatMapAnalysis(PostInverterHeatMapAnalysis post)
        {
            ApiResult<InverterHeatMap> apiResult = new ApiResult<InverterHeatMap>();

            InverterHeatMap inverterHeatMap = new InverterHeatMap();
            try
            {
                var powerStation = await powerStationRepository.GetOneAsync(post.PowerStationId);

                if (powerStation == null)
                {
                    apiResult.Code = "9992";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                var inverterHistories = await overviewRepository.GetListInverterByPowerStationIdAndDate(powerStation.Id, post.SelectedDate);

                inverterHeatMap.XAxis = inverterHistories.Select(x => Convert.ToDateTime(x.TIMESTAMP).ToString("HH:mm")).Distinct().ToList();
                inverterHeatMap.YAxis = inverterHistories.Select(x => x.INVERTERID).Distinct().ToList();
                inverterHeatMap.XAxisOnTime = new List<string>();

                inverterHeatMap.Series = new Dictionary<string, List<HeatMapSeries>>();

                var inverterHistory_group = inverterHistories.GroupBy(x => x.INVERTERID).ToList();
                foreach (var inverterHistory in inverterHistory_group)
                {
                    List<HeatMapSeries> heats = new List<HeatMapSeries>();
                    foreach (var value in inverterHistory)
                    {
                        HeatMapSeries heatMapSeries = new HeatMapSeries();
                        heatMapSeries.X = inverterHeatMap.XAxis.IndexOf(Convert.ToDateTime(value.TIMESTAMP).ToString("HH:mm"));
                        heatMapSeries.Y = inverterHeatMap.YAxis.IndexOf(value.INVERTERID);
                        heatMapSeries.Value = value.KWHKWP;

                        heats.Add(heatMapSeries);
                    }

                    inverterHeatMap.Series.Add(inverterHistory.Key, heats);
                }

                for (var i = 0; i < inverterHeatMap.XAxis.Count(); i++)
                {

                    if (inverterHeatMap.XAxis[i].Substring(3, 2) != "00")
                    {
                        inverterHeatMap.XAxisOnTime.Add("");
                    }
                    else
                    {
                        inverterHeatMap.XAxisOnTime.Add(inverterHeatMap.XAxis[i]);
                    }
                }


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

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

        public async Task<ActionResult> GetExceptionTable(ExceptionSent post)
        {
            List<ExceptionDataTable> exceptionDataTable = new List<ExceptionDataTable>();
            ApiResult<List<ExceptionDataTable>> apiResult = new ApiResult<List<ExceptionDataTable>>();

            PowerStation powerStation = null;

            try
            {
                powerStation = await powerStationRepository.GetOneAsync(post.Id);
                exceptionDataTable = await overviewRepository.GetExceptionTable(post);

                foreach (ExceptionDataTable a in exceptionDataTable)
                {
                    if (string.IsNullOrEmpty(a.FormId))
                    {
                        if (a.Err_status == 1)
                        {
                            a.Function = @$"<a href='javascript:;' class='btn btn-success waves-effect waves-themed mb-3 mr-2 add-btn'>填寫表單</a>";
                        }
                    }
                    else
                    {
                        a.Function = @$"<a href='javascript:;' class='waves-effect waves-themed mb-3 mr-2 edit-btn'>{a.FormId}</a>";
                    }
                }

                apiResult.Code = "0000";
                apiResult.Data = exceptionDataTable;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】");
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            var result = Json(new
            {
                data = apiResult
            });

            return result;
        }

        public async Task<ApiResult<InverterkwhBar>> GetInverterkwhBarAnalysis(PostInverterkwhBarAnalysis post)
        {
            ApiResult<InverterkwhBar> apiResult = new ApiResult<InverterkwhBar>();

            InverterkwhBar inverterkwhBar = new InverterkwhBar();
            try
            {
                var powerStation = await powerStationRepository.GetOneAsync(post.PowerStationId);

                if (powerStation == null)
                {
                    apiResult.Code = "9992";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                switch (post.SelectedType)
                {
                    case 0: //單日
                        var inverterHistoriesDay = await overviewRepository.GetListInverterDayByPowerStationId(powerStation.Id, post.SelectedDate);

                        inverterkwhBar.Labels = inverterHistoriesDay.Select(x => x.TIMESTAMP).Distinct().ToList();
                        inverterkwhBar.Datasets = new Dictionary<string, List<double>>();

                        var inverterHistory_group = inverterHistoriesDay.GroupBy(x => x.INVERTERID).ToList();
                        foreach (var inverterHistory in inverterHistory_group)
                        {

                            List<double> values = new List<double>();
                            foreach(var lable in inverterkwhBar.Labels)
                            {
                                var find = false;
                                foreach (var value in inverterHistory)
                                {
                                    if(value.TIMESTAMP == lable)
                                    {
                                        values.Add(value.KWH);
                                        find = true;
                                        break;
                                    }
                                }

                                if (!find)
                                {
                                    values.Add(0);
                                }
                            }

                            inverterkwhBar.Datasets.Add(inverterHistory.Key, values);
                        }
                        break;

                    case 1: //單月
                        var inverterHistoriesMonth = await overviewRepository.GetListInverterMonthByPowerStationId(powerStation.Id, post.SelectedDate);

                        inverterkwhBar.Labels = inverterHistoriesMonth.Select(x => x.TIMESTAMP).Distinct().ToList();
                        inverterkwhBar.Datasets = new Dictionary<string, List<double>>();

                        var inverterHistoryMonth_group = inverterHistoriesMonth.GroupBy(x => x.INVERTERID).ToList();
                        foreach (var inverterHistory in inverterHistoryMonth_group)
                        {
                            List<double> values = new List<double>();
                            foreach (var lable in inverterkwhBar.Labels)
                            {
                                var find = false;
                                foreach (var value in inverterHistory)
                                {
                                    if (value.TIMESTAMP == lable)
                                    {
                                        values.Add(value.KWH);
                                        find = true;
                                        break;
                                    }
                                }

                                if (!find)
                                {
                                    values.Add(0);
                                }
                            }

                            inverterkwhBar.Datasets.Add(inverterHistory.Key, values);
                        }
                        break;
                    case 2: //單季
                        var startMonth = ""; var endMonth = "";
                        switch (post.SelectedQuaryerly)
                        {
                            case 0:
                                startMonth = string.Format("{0}-01", post.SelectedDate);
                                endMonth = string.Format("{0}-03", post.SelectedDate);
                                break;
                            case 1:
                                startMonth = string.Format("{0}-04", post.SelectedDate);
                                endMonth = string.Format("{0}-06", post.SelectedDate);
                                break;
                            case 2:
                                startMonth = string.Format("{0}-07", post.SelectedDate);
                                endMonth = string.Format("{0}-09", post.SelectedDate);
                                break;
                            case 3:
                                startMonth = string.Format("{0}-10", post.SelectedDate);
                                endMonth = string.Format("{0}-12", post.SelectedDate);
                                break;
                        }

                        var inverterHistoriesQuaryerly = await overviewRepository.GetListInverterQuaryerlyByPowerStationId(powerStation.Id, startMonth, endMonth);



                        inverterkwhBar.Labels = inverterHistoriesQuaryerly.Select(x => x.TIMESTAMP).Distinct().ToList();
                        inverterkwhBar.Datasets = new Dictionary<string, List<double>>();

                        var inverterHistoryQuaryerly_group = inverterHistoriesQuaryerly.GroupBy(x => x.INVERTERID).ToList();
                        foreach (var inverterHistory in inverterHistoryQuaryerly_group)
                        {
                            List<double> values = new List<double>();
                            foreach (var lable in inverterkwhBar.Labels)
                            {
                                var find = false;
                                foreach (var value in inverterHistory)
                                {
                                    if (value.TIMESTAMP == lable)
                                    {
                                        values.Add(value.KWH);
                                        find = true;
                                        break;
                                    }
                                }

                                if (!find)
                                {
                                    values.Add(0);
                                }
                            }

                            inverterkwhBar.Datasets.Add(inverterHistory.Key, values);
                        }
                        break;
                    case 3: //單年
                        var inverterHistoriesYear = await overviewRepository.GetListInverterYearByPowerStationId(powerStation.Id, post.SelectedDate);

                        inverterkwhBar.Labels = inverterHistoriesYear.Select(x => x.TIMESTAMP).Distinct().ToList();
                        inverterkwhBar.Datasets = new Dictionary<string, List<double>>();

                        var inverterHistoryYear_group = inverterHistoriesYear.GroupBy(x => x.INVERTERID).ToList();
                        foreach (var inverterHistory in inverterHistoryYear_group)
                        {
                            List<double> values = new List<double>();
                            foreach (var lable in inverterkwhBar.Labels)
                            {
                                var find = false;
                                foreach (var value in inverterHistory)
                                {
                                    if (value.TIMESTAMP == lable)
                                    {
                                        values.Add(value.KWH);
                                        find = true;
                                        break;
                                    }
                                }

                                if (!find)
                                {
                                    values.Add(0);
                                }
                            }

                            inverterkwhBar.Datasets.Add(inverterHistory.Key, values);
                        }
                        break;
                }

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

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

        public async Task<ApiResult<List<HistoryTable>>> GetTotalTableToHistory(HistorySent post)
        {
            var History = new List<HistoryTable>();
            ApiResult<List<HistoryTable>> apiResult = new ApiResult<List<HistoryTable>>();
            var powerStation = await powerStationRepository.GetOneAsync(post.PowerstationId);

            try
            {
                History = await overviewRepository.GethistoryTable(post);
                foreach (var a in History)
                {
                    switch (post.GroupType)
                    {
                        case 0:
                            a.TOTALTIME = Convert.ToDateTime(a.TIMESTAMP).ToString("yyyy-MM-dd ");
                            a.TIMESTAMP = Convert.ToDateTime(a.TIMESTAMP).ToString("HH tt", CultureInfo.InvariantCulture);
                            break;
                        case 1:
                            a.TOTALTIME = Convert.ToDateTime(a.TIMESTAMP).ToString("yyyy-MM");
                            a.TIMESTAMP = Convert.ToDateTime(a.TIMESTAMP).ToString("yyyy-MM-dd");
                            break;
                        case 2:
                            a.TOTALTIME = Convert.ToDateTime(a.TIMESTAMP).ToString("yyyy");
                            a.TIMESTAMP = Convert.ToDateTime(a.TIMESTAMP).ToString("yyyy-MM");
                            break;
                        case 3:
                            a.TOTALTIME = "";
                            a.TIMESTAMP = Convert.ToDateTime(a.TIMESTAMP).ToString("yyyy");
                            break;
                    }
                }


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