using System;
using System.Linq;
using System.Threading.Tasks;

using FMSAdmin.Data;
using FMSAdmin.Models;
using FMSAdmin.Entities;
using FMSApp.Services;

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
using FMSAdmin.Helpers;
using System.Data;
using System.IO;
using OfficeOpenXml;
using System.Text;
using System.Collections.Generic;
using System.Collections;

namespace FMSAdmin.Controllers {
    [ApiController]
    [ApiVersion("1")]
    [Route("api/[controller]")]
    public class MonthlyReportDataController : Controller {
        private readonly ILogger<MonthlyReportDataController> _logger;
        private readonly MonthlyReportService _service;
        private readonly FMSContext _context;
        private readonly StorageHelper _storage;

        public MonthlyReportDataController(
            ILogger<MonthlyReportDataController> logger,
            MonthlyReportService service,
            FMSContext context,
            StorageHelper storage
            ) {
            _logger = logger;
            _service = service;
            _context = context;
            _storage = storage;
        }

        /// <summary>
        // 법정검사
        /// </summary>
        [HttpGet("[action]")]
        public IActionResult LegalExamination(int siteId, int year, int month) {
            var site = _context.CmSite.Where(x => x.SiteId == siteId).FirstOrDefault();
            if (site == null) {
                return BadRequest("사이트가 없습니다.");
            }
            DataTable legalExamination = _service.GetLegalExamination(siteId, new DateTime(year, month, 1));

            return Ok(new {
                Site = new {
                    site.SiteId,
                    site.Name,
                },
                LegalExamination = legalExamination,
            });
        }


        /// <summary>
        /// 기온변동현황
        /// </summary>
        [HttpGet("[action]")]
        public IActionResult CurrentTempHumidity(int siteId, int year, int month) {

            var site = _context.CmSite.Where(x => x.SiteId == siteId).FirstOrDefault();
            if (site == null) {
                return BadRequest("사이트가 없습니다.");
            }

            Func<int, int, (Hashtable, IQueryable<dynamic>)> maxTemp = (int y, int m) => {
                Hashtable table = new Hashtable();
                table["Year"] = y;
                var query = from x in _context.SiteWeatherInfo
                            where x.CurrentTemp != null
                                && x.Sido == site.ApiSido && x.Sigun == site.ApiSigun
                                && x.BaseTime.Hour >= 9 && x.BaseTime.Hour <= 18
                                && x.BaseTime.Month == m && x.BaseTime.Year == y
                            group x by x.BaseTime.Date into g
                            select new {
                                Day = g.Key.Day,
                                Year = g.Key.Year,
                                Temp = g.Max(x => x.CurrentTemp),
                            };

                foreach (var item in query) {
                    table["Day" + item.Day] = item.Temp;
                }
                table["Avg"] = Math.Round(query.Average(x => x.Temp) ?? 0, 2);
                var lastday = DateTime.DaysInMonth(y, m);
                for (var i = 0; i < lastday; i++) {
                    if (table["Day" + (i + 1)] == null) {
                        table["Day" + (i + 1)] = "-";
                    }
                }
                if (lastday < 31) {
                    for (var i = 0; i < 31 - lastday; i++) {
                        table["Day" + (lastday + i + 1)] = "";
                    }
                }
                return (table, query);
            };

            Func<int, int, (Hashtable, IQueryable<dynamic>)> minTemp = (int y, int m) => {
                Hashtable table = new Hashtable();
                table["Year"] = y;
                var query = from x in _context.SiteWeatherInfo
                            where x.CurrentTemp != null
                                && x.Sido == site.ApiSido && x.Sigun == site.ApiSigun
                                && x.BaseTime.Hour >= 9 && x.BaseTime.Hour <= 18
                                && x.BaseTime.Month == m && x.BaseTime.Year == y
                            group x by x.BaseTime.Date into g
                            select new {
                                Day = g.Key.Day,
                                Year = g.Key.Year,
                                Temp = g.Min(x => x.CurrentTemp),
                            };

                foreach (var item in query) {
                    table["Day" + item.Day] = item.Temp;
                }
                table["Avg"] = Math.Round(query.Average(x => x.Temp) ?? 0, 2);
                var lastday = DateTime.DaysInMonth(y, m);
                for (var i = 0; i < lastday; i++) {
                    if (table["Day" + (i + 1)] == null) {
                        table["Day" + (i + 1)] = "-";
                    }
                }
                if (lastday < 31) {
                    for (var i = 0; i < 31 - lastday; i++) {
                        table["Day" + (lastday + i + 1)] = "";
                    }
                }
                return (table, query);
            };

            Func<int, int, (Hashtable, IQueryable<dynamic>)> avgHumi = (int y, int m) => {
                Hashtable table = new Hashtable();
                table["Year"] = y;
                var query = from x in _context.SiteWeatherInfo
                            where x.Humidity != null
                                && x.Sido == site.ApiSido && x.Sigun == site.ApiSigun
                                && x.BaseTime.Hour >= 9 && x.BaseTime.Hour <= 18
                                && x.BaseTime.Month == m && x.BaseTime.Year == y
                            group x by x.BaseTime.Date into g
                            select new {
                                Day = g.Key.Day,
                                Year = g.Key.Year,
                                Humidity = g.Average(x => x.Humidity),
                            };

                foreach (var item in query) {
                    table["Day" + item.Day] = Math.Round(item.Humidity ?? 0, 2);
                }
                table["Avg"] = Math.Round(query.Average(x => x.Humidity) ?? 0, 2);
                var lastday = DateTime.DaysInMonth(y, m);
                for (var i = 0; i < lastday; i++) {
                    if (table["Day" + (i + 1)] == null) {
                        table["Day" + (i + 1)] = "-";
                    }
                }
                if (lastday < 31) {
                    for (var i = 0; i < 31 - lastday; i++) {
                        table["Day" + (lastday + i + 1)] = "";
                    }
                }

                return (table, query);
            };

            var (maxTempMap1, maxTempRaw1) = maxTemp(year - 1, month);
            var (maxTempMap2, maxTempRaw2) = maxTemp(year, month);
            var (minTempMap1, minTempRaw1) = minTemp(year - 1, month);
            var (minTempMap2, minTempRaw2) = minTemp(year, month);
            var (avgHumiMap1, avgHumiRaw1) = avgHumi(year - 1, month);
            var (avgHumiMap2, avgHumiRaw2) = avgHumi(year, month);

            IList<dynamic> maxTempChart = new List<dynamic>();
            for (var day = 1; day <= 31; day++) {
                string val1 = maxTempMap1["Day" + day] as string;
                string val2 = maxTempMap2["Day" + day] as string;
                maxTempChart.Add(new {
                    Day = day,
                    Val1 = val1 == "-" || val1 == "" ? null : maxTempMap1["Day" + day],
                    Val2 = val2 == "-" || val2 == "" ? null : maxTempMap2["Day" + day],
                });
            }

            IList<dynamic> minTempChart = new List<dynamic>();
            for (var day = 1; day <= 31; day++) {
                string val1 = minTempMap1["Day" + day] as string;
                string val2 = minTempMap2["Day" + day] as string;
                minTempChart.Add(new {
                    Day = day,
                    Val1 = val1 == "-" || val1 == "" ? null : minTempMap1["Day" + day],
                    Val2 = val2 == "-" || val2 == "" ? null : minTempMap2["Day" + day],
                });
            }

            IList<dynamic> avgHumiChart = new List<dynamic>();
            for (var day = 1; day <= 31; day++) {
                string val1 = avgHumiMap1["Day" + day] as string;
                string val2 = avgHumiMap2["Day" + day] as string;
                avgHumiChart.Add(new {
                    Day = day,
                    Val1 = val1 == "-" || val1 == "" ? null : avgHumiMap1["Day" + day],
                    Val2 = val2 == "-" || val2 == "" ? null : avgHumiMap2["Day" + day],
                });
            }

            return Ok(new {
                Site = new {
                    site.SiteId,
                    site.Name,
                },
                MaxTemp1 = maxTempMap1,
                MaxTemp2 = maxTempMap2,
                MinTemp1 = minTempMap1,
                MinTemp2 = minTempMap2,
                AvgHumi1 = avgHumiMap1,
                AvgHumi2 = avgHumiMap2,
                MaxTempChart = maxTempChart,
                MinTempChart = minTempChart,
                AvgHumiChart = avgHumiChart,
            });
        }


    }
}