using Microsoft.Extensions.Logging;
using FMSAdmin.Data;
using System.Linq;
using FMSAdmin.Helpers;
using FMSAdmin.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using FMSAdmin.Models.Formula;
using FMSAdmin.Helpers.Formula;
using System.Collections;
using System.Text.RegularExpressions;
using FMSAdmin.Models;

namespace FMSAdmin.Services {
    public class EnergyDayAnalysisService {
        private readonly ILogger<EnergyDayAnalysisService> _logger;
        private readonly FMSContext _context;
        private readonly EnergyUsageService _serviceUsage;

        public EnergyDayAnalysisService(
            ILogger<EnergyDayAnalysisService> logger,
            FMSContext context,
            EnergyUsageService serviceUsage
        ) {
            _logger = logger;
            _context = context;
            _serviceUsage = serviceUsage;
        }

        public IList<CalculationResult> GetEnergyDailyList(int siteId, EnergyInterval interval, EnergyType type, DateTime startDate, DateTime endDate) {
            var dic = _serviceUsage.GetEnergyDailyDic(siteId, interval, type, startDate, endDate);
            return dic.Values.ToList();
        }

        public CalculationValue[] GetMonitoringPointHistoryDaily(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) {
            var query = _context.BemsMonitoringPointHistoryDaily.Where(x =>
                    x.SiteId == siteId &&
                    x.FacilityCode == facilityCode &&
                    x.PropertyId == propertyId &&
                    startDate <= x.CreatedDateTime && x.CreatedDateTime <= endDate);

            if (query.Any() == false) {
                return null;
            }

            return query.Select(x => new CalculationValue {
                DateTime = x.CreatedDateTime,
                Value = x.DailyValue
            }).ToArray();
        }

        public CalculationValue[] GetMonitoringPointHistoryMonthly(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) {
            var groupQuery = from data in _context.BemsMonitoringPointHistoryDaily
                             where data.SiteId == siteId &&
                                   data.FacilityCode == facilityCode &&
                                   data.PropertyId == propertyId &&
                                   startDate <= data.CreatedDateTime && data.CreatedDateTime <= endDate
                             group data by new { Year = data.CreatedDateTime.Year, Month = data.CreatedDateTime.Month } into g
                             // select g;
                             select new {
                                 Year = g.Key.Year,
                                 Month = g.Key.Month,
                                 SumDailyValue = g.Sum(x => x.DailyValue),
                                 AverageDailyValue = g.Average(x => x.DailyValue)
                             };

            if (groupQuery == null || groupQuery.Any() == false) {
                return null;
            }

            //CalculationValue[] values = { };// = new CalculationValue[groupQuery.ToList().Count()];
            CalculationValue[] values = new CalculationValue[groupQuery.ToList().Count()];

            var i = 0;
            foreach (var g in groupQuery.ToList()) {
                double dValue = 0;
                if (_CheckPointValueType(siteId, facilityCode, propertyId) == 0) dValue = g.SumDailyValue;
                else if (_CheckPointValueType(siteId, facilityCode, propertyId) == 1) dValue = g.AverageDailyValue;
                else if (_CheckPointValueType(siteId, facilityCode, propertyId) == 2) {
                    dValue = g.SumDailyValue;
                    dValue = (dValue > 0) ? 1 : 0;
                }
                values[i] = new CalculationValue {
                    DateTime = new DateTime(g.Year, g.Month, 1),
                    //Value = g.Sum(x => x.CurrentValue)
                    Value = dValue
                };

                i++;
            }

            return values;
        }

        private int _CheckPointValueType(int siteId, int facilityCode, int propertyId) {
            // return 0 -> 누적, 1 -> 평균,  2 -> On,Off
            var Query = from data in _context.BemsMonitoringPoint
                        where data.SiteId == siteId &&
                                data.FacilityCode == facilityCode &&
                                data.PropertyId == propertyId
                        select data;

            if (Query.FirstOrDefault().ValueType == 2) return 2;

            if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId > 0) return 0;
            if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId == 0) return 1;
            return 0;
        }

        private CalculationValue[] _CreateCalculationValues(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) {
            DateTime datetime = startDate;
            int count = _GetCountInTimeRange(startDate, endDate, timeIntervalType);
            CalculationValue[] values = new CalculationValue[count];

            for (var i = 0; i < values.Length; i++) {
                values[i] = new CalculationValue {
                    DateTime = datetime,
                    Value = 0
                };
                _NextTimeFromTimeInterval(ref datetime, timeIntervalType);
            }
            return values;
        }

        private int _GetCountInTimeRange(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) {
            TimeSpan ts = endDate - startDate;
            switch (timeIntervalType) {
                case TimeInterval.QuarterMin:
                    return (int)ts.TotalMinutes / 15 + 1;
                case TimeInterval.Hour:
                    return (int)ts.TotalHours + 1;
                case TimeInterval.Day:
                    return (int)ts.TotalDays + 1;
                case TimeInterval.Month: {
                        int count = 0;
                        DateTime date = startDate;
                        //while (date.Year <= endDate.Year && date.Month <= endDate.Month)
                        while (date <= endDate) {
                            count++;
                            date = date.AddMonths(1);
                        }
                        return count;
                    }
                default: // TimeInterval.Year:
                    {
                        int count = 0;
                        DateTime date = startDate;
                        while (date.Year <= endDate.Year) {
                            count++;
                            date = date.AddYears(1);
                        }
                        return count;
                    }
            }

        }
        private void _NextTimeFromTimeInterval(ref DateTime datetime, TimeInterval timeIntervalType) {
            switch (timeIntervalType) {
                case TimeInterval.QuarterMin:
                    datetime = datetime.AddMinutes(15);
                    break;
                case TimeInterval.Hour:
                    datetime = datetime.AddHours(1);
                    break;
                case TimeInterval.Day:
                    datetime = datetime.AddDays(1);
                    break;
                case TimeInterval.Month:
                    datetime = datetime.AddMonths(1);
                    break;
                default: // TimeInterval.Year:
                    datetime = datetime.AddYears(1);
                    break;
            }
        }

        public void Save(int siteId, int fuelTypeId, int fuelPriceId, int year, int month, int priceTypeId, FmsEnergyAnalysis data) {
            var persist = _context.FmsEnergyAnalysis
                            .Where(x => x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.FuelPriceId == fuelPriceId && x.Year == year && x.Month == month && x.PriceTypeId == priceTypeId).FirstOrDefault();
            if (persist == null) {
                data.PriceTypeId = priceTypeId;
                data.Year = year;
                data.Month = month;
                _context.FmsEnergyAnalysis.Add(data);
                _context.SaveChanges();
            } else {
                persist.PriceTypeId = priceTypeId;
                persist.Year = year;
                persist.Month = month;
                persist.Content = data.Content;
                _context.FmsEnergyAnalysis.Update(persist);
                _context.SaveChanges();
            }
        }

        public IQueryable<FmsEnergyAnalysis> GetAnalysis(int siteId, int fuelTypeId, int fuelPriceId, string year, string month, int priceTypeId) {
            var data = _context.FmsEnergyAnalysis.Where(x => x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.FuelPriceId == fuelPriceId && x.Year == Convert.ToInt32(year) && x.Month == Convert.ToInt32(month) && x.PriceTypeId == priceTypeId);

            return data;
        }

        public IQueryable<FmsEnergyAnalysis> GetAllAnalysis(int siteId, int fuelTypeId, int year, int month) {
            var data = _context.FmsEnergyAnalysis.Where(x => x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.Year == year && x.Month == month);

            return data;
        }
    }
}