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;

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

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



        /// <summary>
        /// 목록
        /// </summary>
        [HttpGet]
        public IActionResult List([FromQuery] PagingRequest req, int? siteId, int depth, int? buildingId, int? floorId, int? zoneId) {
            var query = _FilterAndSort(req, depth, siteId, buildingId, floorId, zoneId);

            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,
                x.ValueType,
                ValueTypeName = x.ValType.Name,
                x.BuildingId,
                x.FloorId,
                x.ZoneId,
                Location = x.CmBuilding.Name + " " + x.CmFloor.Name + " " + x.CmZone.Name,
            });
            return list;
        }

        // 검색 & 정렬 공통
        private IQueryable<BemsMonitoringPoint> _FilterAndSort(PagingRequest req, int depth, int? siteId, int? buildingId, int? floorId, int? zoneId) {
            var query = _service.GetAll();

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

            query = query.Where(x => x.FacilityTypeId < 100);

            if (req.siteId != null) {
                query = query.Where(x => x.SiteId == Util.ToInt(req.siteId));
            }
            if (depth >= 1 || depth == 0) {
                query = query.Where(x => x.BuildingId == Util.ToInt(buildingId));
            }
            if (depth >= 2 || depth == 0) {
                query = query.Where(x => x.FloorId == Util.ToInt(floorId));
            }
            if (depth >= 3 || depth == 0) {
                query = query.Where(x => x.ZoneId == Util.ToInt(zoneId));
            }

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

            return query;
        }

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

            if (ModelState.IsValid) {
                _service.Edit(siteId, 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) {
            try {
                _service.Delete(data);
            } catch {
                throw new ServiceException("이미 다른 화면에서 사용중이므로 삭제할 수 없습니다.");
            }
            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 locationTreeItem = _context.CmBuilding.Where(x => x.SiteId == siteId).Select(x => new {
                key = 'b' + x.BuildingId,
                title = x.Name,
                depth = 1,
                buildingId = x.BuildingId,
                floorId = 0,
                zoneId = 0,
                children = _context.CmFloor.Where(f => f.SiteId == siteId && f.BuildingId == x.BuildingId).Select(f => new {
                    key = 'f' + f.FloorId,
                    title = f.Name,
                    depth = 2,
                    buildingId = f.BuildingId,
                    floorId = f.FloorId,
                    zoneId = 0,
                    children = _context.CmZone.Where(z => z.SiteId == siteId && z.BuildingId == f.BuildingId && z.FloorId == f.FloorId).Select(z => new {
                        key = 'z' + z.ZoneId,
                        title = z.Name,
                        depth = 3,
                        buildingId = z.BuildingId,
                        floorId = z.FloorId,
                        zoneId = z.ZoneId,
                    }).ToList(),
                }).ToList(),
            });

            return Ok(locationTreeItem);
        }


    }
}