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

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

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using FMSAdmin.Helpers;
using System.Data;
using System.IO;
using OfficeOpenXml;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using System.Collections;

namespace FMSAdmin.Controllers {
    [Authorize]
    [ApiController]
    [ApiVersion("1")]
    [Route("api/[controller]")]
    public class HolidayController : Controller {
        private readonly ILogger<HolidayController> _logger;
        private readonly FMSContext _context;
        private readonly HolidayService _service;
        private readonly StorageHelper _storage;
        private readonly MonthWorkService _serviceMonthWork;
        public HolidayController(
            ILogger<HolidayController> logger,
            FMSContext context,
            HolidayService service,
            MonthWorkService serviceMonthWork,
            StorageHelper storage
            ) {
            _logger = logger;
            _context = context;
            _service = service;
            _storage = storage;
            _serviceMonthWork = serviceMonthWork;
        }

        /// <summary>
        /// 목록
        /// </summary>
        [HttpGet("[action]")]
        public IActionResult ListCalendar(int siteId, int? year, int? month) {
            DateTime selectMonth;
            if (year == null || month == null) {
                selectMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            } else {
                selectMonth = new DateTime(year.Value, month.Value, 1);
            }
            var startDate = selectMonth.AddDays(-7);
            var endDate = selectMonth.AddDays(37);

            // 휴일
            var holidayList = _GetHolidayList(siteId, selectMonth.Year, selectMonth.Month, startDate, endDate);

            // 주말
            var weekend = _context.CmHolidayWeekend.Where(
                x => x.SiteId == siteId
                && x.IsUse == true
            ).FirstOrDefault();

            if (weekend != null) {
            }

            // 주별 중점업무
            var weekList = _GetWeekKeyWorkEventList(siteId, startDate, endDate);

            var workName = _serviceMonthWork.GetKeyWork(siteId, selectMonth.Month);
            var result = new {
                Year = selectMonth.Year,
                Month = selectMonth.Month,
                Theme = workName,
                StartDate = startDate.ToString("yyyy-MM-dd"),
                EndDate = endDate.ToString("yyyy-MM-dd"),
                HolidayList = holidayList,
                Saturday = weekend?.Saturday ?? false,
                Sunday = weekend?.Sunday ?? false,
                WeekList = weekList
            };

            return Ok(result);
        }

        /// <summary>
        /// 휴일 조회 (정기/특정)
        /// </summary>
        [HttpGet("{siteId}/{type}/{id}")]
        public IActionResult Get(int siteId, string type, string id) {
            if (type == "H") {      //정기                
                var array = id.Split('-');
                int month = Util.ToInt(array[0]);
                int day = Util.ToInt(array[1]);
                var data = _service.Gets(month, day, siteId);
                if (data.Count() == 0) {
                    return NotFound("휴일 정보를 찾을 수 없습니다.");
                }
                var item = data.Select(x => new {
                    x.SiteId,
                    SiteName = x.Site.Name,
                    CmSite = new {
                        x.Site.Name,
                    },
                    x.HolidayMonth,
                    x.HolidayDay,
                    x.IsLunar,
                    x.Name,
                    HolidayType = "H",
                    isHolidayType = true,
                    x.IsUse
                });

                return Ok(item.First());
            } else if (type == "C") {       //특정
                var data = _service.CustomGets(id, siteId);
                if (data.Count() == 0) {
                    return NotFound("휴일 정보를 찾을 수 없습니다.");
                }
                var item = data.Select(x => new {
                    x.SiteId,
                    SiteName = x.Site.Name,
                    CmSite = new {
                        x.Site.Name,
                    },
                    x.HolidayDate,
                    x.Name,
                    HolidayType = "C",
                    isHolidayType = false,
                    x.IsUse
                });

                return Ok(item.First());
            } else {
                return Ok();
            }
        }

        /// <summary>
        /// 등록
        /// </summary>
        [HttpPut("{dates}")]
        public IActionResult Create(string dates, [FromBody] CmHoliday data) {
            _logger.LogInformation("Create");
            //_logger.LogInformation(data.Dump());

            if (ModelState.IsValid) {
                _service.Create(dates, data);
            } else {
                return BadRequest(ModelState);
            }
            return Ok();
        }

        /// <summary>
        /// 수정
        /// </summary>
        [HttpPost("{siteId}/{id}")]
        public IActionResult Edit(int siteId, string id, [FromBody] CmHoliday data) {
            string[] arrId = id.Split('-');
            if (Util.ToInt(arrId[0]) != data.HolidayMonth || Util.ToInt(arrId[1]) != data.HolidayDay) {
                return BadRequest("잘못된 접근입니다.");
            }

            if (ModelState.IsValid) {
                _service.Edit(Util.ToInt(arrId[0]), Util.ToInt(arrId[1]), siteId, data);
            } else {
                return BadRequest(ModelState);
            }

            return Ok();
        }

        /// <summary>
        /// 삭제
        /// </summary>
        [HttpDelete("{siteId}/{dates}")]
        public IActionResult Delete(int siteId, string dates) {
            _service.Delete(dates, siteId);

            return Ok();
        }

        private IList<CalendarBackground> _GetHolidayList(int siteId, int year, int month, DateTime startDate, DateTime endDate) {
            var list = new List<CalendarBackground>();

            var holiday = _context.CmHoliday.Where(
                x => x.SiteId == siteId
                && x.IsUse == true
            ).ToList();
            foreach (var item in holiday) {
                DateTime dt;
                if (!DateTime.TryParse(year.ToString() + "-" + item.HolidayMonth.ToString("D2") + "-" + item.HolidayDay.ToString("D2"), out dt)) {
                    continue;
                }
                if (item.IsLunar) {
                    var solar = LunarSolarConverter.LunarToSolar(new Lunar() {
                        lunarYear = year,
                        lunarMonth = item.HolidayMonth,
                        lunarDay = item.HolidayDay
                    });
                    list.Add(new CalendarBackground {
                        Id = "H-" + item.SiteId + "-" + item.HolidayMonth.ToString() + "-" + item.HolidayDay.ToString(),
                        Title = item.Name + "(음력)",
                        Date = new DateTime(solar.solarYear, solar.solarMonth, solar.solarDay).ToString("yyyy-MM-dd"),
                        SunDate = new DateTime(year, item.HolidayMonth, item.HolidayDay).ToString("yyyy-MM-dd"),
                        Type = "H",
                        IsLunar = item.IsLunar,
                    });
                } else {
                    list.Add(new CalendarBackground {
                        Id = "H-" + item.SiteId + "-" + item.HolidayMonth.ToString() + "-" + item.HolidayDay.ToString(),
                        Title = item.Name,
                        Date = new DateTime(year, item.HolidayMonth, item.HolidayDay).ToString("yyyy-MM-dd"),
                        Type = "H",
                        IsLunar = false,
                    });
                }
            }

            var holiday2 = _context.CmHolidayCustom.Where(x => x.SiteId == siteId && x.HolidayDate.Date >= startDate.Date && x.HolidayDate <= endDate.Date).ToList();
            foreach (var item in holiday2) {
                list.Add(new CalendarBackground {
                    Id = "C-" + item.SiteId + "-" + item.HolidayDate.ToString("yyyyMMdd"),
                    Title = item.Name,
                    Date = item.HolidayDate.ToString("yyyy-MM-dd"),
                    Type = "C",
                });
            }

            return list;
        }

        private IQueryable<CalendarEvent> _GetWeekKeyWorkEventList(int? siteId, DateTime startDate, DateTime endDate) {
            var query = _context.FmsWeekKeyWork.Select(x => x);
            if (siteId != null) {
                query = query.Where(x => x.SiteId == siteId.Value);
            }
            query = query.Where(x => x.WorkDate.Date >= startDate.Date && x.WorkDate.Date <= endDate.Date);

            var list = query.Select(x => new CalendarEvent {
                Title = x.WorkName,
                Start = x.WorkDate.ToString("yyyy-MM-dd"),
                End = x.WorkDate.AddDays(7).ToString("yyyy-MM-dd"),
                WorkType = "주별중점업무",
                Type = "주별 중점업무",
                WorkRequestId = x.WeekKeyWorkId,
                SiteId = x.SiteId,
            });

            return list;
        }
    }
}