using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;

using FMSAdmin.Data;
using FMSAdmin.Helpers;
using FMSAdmin.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using FMSAdmin.Models;
using FMSAdmin.Models.Formula;

namespace FMSApp.Services {
    public class FormulaService {
        private readonly ILogger<FormulaService> _logger;
        private readonly FMSContext _context;

        public FormulaService(
            ILogger<FormulaService> logger,
            FMSContext context) {
            _logger = logger;
            _context = context;
        }
        public CalculationValue[] GetPointValues(int siteId,
            int facilityCode, int propertyId, TimeInterval timeIntervalType,
            DateTime startDate, DateTime endDate) {
            switch (timeIntervalType) {
                case TimeInterval.QuarterMin:
                    return GetMonitoringPointHistory15min(
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Hour:
                    return GetMonitoringPointHistoryHourly(
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Day:
                    return GetMonitoringPointHistoryDaily(
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Month:
                    return GetMonitoringPointHistoryMonthly(
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                case TimeInterval.Year:
                    return GetMonitoringPointHistoryYearly(
                        siteId,
                        facilityCode,
                        propertyId,
                        startDate,
                        endDate);

                default:
                    throw new Exception("IntervalType Value Error!");
            }
        }
        public CalculationValue[] GetMonitoringPointHistory15min(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) {
            var query = _context.BemsMonitoringPointHistory15min.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.CurrentValue
            }).ToArray();
        }

        public CalculationValue[] GetMonitoringPointHistoryHourly(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) {
            var query = _context.BemsMonitoringPointHistoryHourly.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.CurrentValue

            }).ToArray();
        }
        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;
        }
        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;
        }
        public CalculationValue[] GetMonitoringPointHistoryYearly(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 } into g
                             select g;

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

            CalculationValue[] values = new CalculationValue[groupQuery.Count()];
            var i = 0;
            foreach (var g in groupQuery) {
                values[i] = new CalculationValue {
                    DateTime = new DateTime(g.Key.Year, 1, 1),
                    //Value = g.Sum(x => x.CurrentValue)
                    Value = g.Sum(x => x.DailyValue)
                };
                i++;
            }

            return values;
        }

    }
}