using System;
using System.Collections.Generic;

using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using FMSAdmin.Data;
using FMSAdmin.Models;
using FMSAdmin.Helpers;
using FMSAdmin.Entities;
using FMSAdmin.Services;
using Microsoft.AspNetCore.Authorization;
using System.IO;
using OfficeOpenXml;

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

        public MonitoringPointController(
            ILogger<MonitoringPointController> logger,
            FMSContext context,
            MonitoringPointService service
            ) {
            _logger = logger;
            _context = context;
            _service = service;
        }



        /// <summary>
        /// 목록
        /// </summary>
        [HttpGet]
        public IActionResult List([FromQuery] PagingRequest req, int? siteId, int? type, int? facilityTypeId, int? facilityCode) {
            var query = _FilterAndSort(req);
            if (siteId != null) {
                query = query.Where(
                    x => x.SiteId == siteId
                );
            }
            if (type != null) {
                if (type == 1) query = query.Where(x => x.FacilityTypeId == 99);
                if (type == 2) query = query.Where(x => x.FacilityTypeId < 99);
                //if (type == 3) query = query.Where(x => x.FacilityTypeId != 99);
            }
            if (facilityTypeId != null) {
                query = query.Where(
                    x => x.FacilityTypeId == facilityTypeId
                );
            }
            if (facilityCode != null) {
                query = query.Where(
                    x => x.FacilityCode == facilityCode
                );
            }

            var list = _ListSelect(query);



            var paging = PagingList.Pagination(list, req.page, req.limit);
            return Ok(paging);
        }

        /// <summary>
        /// 목록
        /// </summary>
        [HttpGet]
        private dynamic _ListSelect(IQueryable<BemsMonitoringPoint> query) {

            var list = query.Select(x => new {
                x.SiteId,
                CmSite = x.CmFacility.CmSite.Name,
                x.FacilityTypeId,
                FacilityTypeName = x.FacilityType.Name,
                x.FacilityCode,
                x.PropertyId,
                CmFacilityName = x.CmFacility.Name,
                x.Name,
                ServiceTypeName = x.ServiceType.Name,
                FuelTypeName = x.FuelType.Name,
                BemsValueTypeName = x.ValType.Name,
            });
            return list;
        }

        // 검색 & 정렬 공통
        private IQueryable<BemsMonitoringPoint> _FilterAndSort(PagingRequest req) {
            var query = _service.GetAll();

            // 기본 Entity 검색
            query = query.Filter(req.conditions);

            // 기본 Entity 정렬
            query = query.Sort(req.sort);

            return query;
        }


        /// <summary>
        /// 등록
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPut]
        public IActionResult Create([FromBody] BemsMonitoringPoint data) {
            //_logger.LogInformation(data.Dump());

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

        /// <summary>
        /// 수정
        /// </summary>
        /// <param name="id"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost("{siteId}/{facilityCode}/{propertyId}")]
        public IActionResult Edit(int siteId, int facilityCode, int propertyId, [FromBody] BemsMonitoringPoint data) {
            //_logger.LogInformation(data.Dump());

            if (ModelState.IsValid) {
                _service.Edit(siteId, facilityCode, propertyId, data);
            } else {
                return BadRequest(ModelState);
            }
            return Ok();
        }

        /// <summary>
        /// 삭제
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        //[HttpDelete("{siteId}")]
        [HttpPost("[action]")]
        public IActionResult Delete([FromBody] List<BemsMonitoringPoint> data) {
            _service.Delete(data);
            return Ok();
        }

        /// <summary>
        /// 관제점초기생성
        /// </summary>
        /// <returns></returns>
        //[HttpDelete("{siteId}")]
        [HttpGet("[action]")]
        public IActionResult Init(int siteId, int facilityTypeId, int facilityCode) {
            _service.Deletes(siteId, facilityCode);
            _service.CreateAll(siteId, facilityCode, facilityTypeId);
            return Ok();
        }

        /// <summary>
        /// 조회
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{siteId}/{facilityCode}/{propertyId}")]
        public IActionResult Get(int siteId, int facilityCode, int propertyId) {
            var data = _service.Get(siteId, facilityCode, propertyId);
            // var data = _service.GetAll()
            //     .Where(x => x.SiteId == siteId && x.FacilityCode == facilityCode && x.PropertyId == propertyId);
            if (data.Count() == 0) {
                return NotFound("정보를 찾을 수 없습니다.");
            }
            var item = data.Select(x => new {
                x.SiteId,
                CmSite = new {
                    x.CmFacility.CmSite.Name
                },
                x.FacilityTypeId,
                FacilityTypeName = new {
                    x.FacilityType.Name
                },
                x.FacilityCode,
                Facility = new {
                    x.CmFacility.Name
                },
                x.PropertyId,
                x.ValueType,
                ValueName = new {
                    x.ValType.Name
                },
                ServiceName = new {
                    x.ServiceType.Name
                },
                x.ServiceTypeId,
                FuelName = new {
                    x.FuelType.Name
                },
                x.FuelTypeId,
                x.Name,
                x.Description,
            });

            return Ok(item.First());
        }

        /// <summary>
        /// 자식 노드 리스트
        /// </summary>
        /// <param name="parentId"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        [HttpGet("childs/{siteId}")]
        public IActionResult Childs(int siteId) {
            var virtualFacility = from x in _context.BemsFacilityType
                                  where x.FacilityTypeId == 99
                                  orderby x.FacilityTypeId ascending
                                  select new {
                                      key = x.FacilityTypeId,
                                      title = x.Name,
                                      depth = 0,
                                      FacilityTypeId = x.FacilityTypeId,
                                      type = "v",
                                      children = _context.CmFacility.Where(item => item.FacilityTypeId == x.FacilityTypeId && item.SiteId == siteId && item.IsVirtualFacility && item.IsUse != false).Select(c => new {
                                          key = c.FacilityCode,
                                          title = c.Name,
                                          depth = 1,
                                          FacilityTypeId = c.FacilityTypeId,
                                          type = "v"
                                      }).ToList()
                                  };


            var normalFacility = from x in _context.BemsFacilityType
                                 where x.FacilityTypeId < 99
                                 orderby x.FacilityTypeId ascending
                                 select new {
                                     key = x.FacilityTypeId,
                                     title = x.Name,
                                     depth = 0,
                                     FacilityTypeId = x.FacilityTypeId,
                                     type = "n",
                                     children = _context.CmFacility.Where(item => item.FacilityTypeId == x.FacilityTypeId && item.SiteId == siteId && !item.IsVirtualFacility && item.IsUse == true).Select(c => new {
                                         key = c.FacilityCode,
                                         title = c.Name,
                                         FacilityTypeId = c.FacilityTypeId,
                                         depth = 1,
                                         type = "n"
                                     }).ToList()
                                 };

            var result = new {
                virtualFacility,
                normalFacility
            };

            return Ok(result);
        }

        /// <summary>
        /// 엑셀파일 익스포트
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpGet("excel")]
        public IActionResult ExportExcel([FromQuery] PagingRequest req, int? siteId, int? type, int? facilityTypeId, int? facilityCode, string filename) {
            req.page = 1;
            req.limit = 0;

            var query = _FilterAndSort(req);
            if (siteId != null) {
                query = query.Where(
                    x => x.SiteId == siteId
                );
            }
            if (type != null) {
                if (type == 1) query = query.Where(x => x.FacilityTypeId == 99);
                if (type == 2) query = query.Where(x => x.FacilityTypeId < 99);
            }
            if (facilityTypeId != null) {
                query = query.Where(
                    x => x.FacilityTypeId == facilityTypeId
                );
            }
            if (facilityCode != null) {
                query = query.Where(
                    x => x.FacilityCode == facilityCode
                );
            }


            var list = query.Select(x => new {
                FacilityTypeName = x.FacilityType.Name,
                CmFacilityName = x.CmFacility.Name,
                x.Name,
                FuelTypeName = x.FuelType.Name,
                ServiceTypeName = x.ServiceType.Name,

            });

            var stream = new MemoryStream();
            using (var package = new ExcelPackage(stream)) {
                var workSheet = package.Workbook.Worksheets.Add("Sheet1");

                workSheet.Cells.LoadFromCollection(list, true);

                if (req.columns != null && req.columns.Length > 0) {
                    workSheet.AddStyle(req.columns, req.sort?.order?.ToLower() == "asc", filename);
                }
                package.Save();
            }
            stream.Position = 0;
            string excelName = $"excel-{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.xlsx";
            return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", excelName);
        }

    }
}