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;

namespace FMSApp.Controllers {
    [Authorize]
    [ApiController]
    [ApiVersion("1")]
    [Route("api/app/users")]
    public class UserController : Controller {
        private readonly ILogger<UserController> _logger;
        private readonly FMSContext _context;
        private readonly UserService _service;
        private readonly StorageHelper _storage;

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

        /// <summary>
        /// 로그인
        /// </summary>
        [AllowAnonymous]
        [HttpPost("[action]")]
        public IActionResult SignIn([FromBody] SignInModel model) {
            _logger.LogInformation(model.Dump());

            var user = _service.Login(int.Parse(model.SiteId), model.UserId, model.Passwd, null);

            if (user == null)
                return BadRequest("아이디나 비밀번호가 잘못되었습니다.");
            if (user.EmploymentStatus == EmploymentStatus.퇴직)
                return BadRequest("로그인 할 수 없습니다.");
            return Ok(new {
                user.SiteId,
                SiteName = user.CmSite.Name,
                user.UserId,
                user.UserGroupId,
                user.Name,
                user.OfficePhoneNo,
                user.Email,
                user.AccessToken,
                IsChangePassword = (user.PasswordUpdatedDate != null && user.PasswordUpdatedDate < DateTime.Now.AddMonths(-3))
            });
        }

        [HttpPost("verify/{siteid}/{userid}")]
        public IActionResult Verify(int siteid, string userid) {
            var verifyKey = User.Identity.Name;
            _logger.LogInformation(verifyKey.ToString());

            var user = _service.GetByUserId(siteid, userid);

            if (user == null) return NotFound();
            if (verifyKey != user.UserId) return NotFound();

            return Ok(new {
                user.SiteId,
                user.UserId,
                user.UserGroupId,
                user.Name,
                user.OfficePhoneNo,
                user.Email,
                IsChangePassword = (user.PasswordUpdatedDate != null && user.PasswordUpdatedDate < DateTime.Now.AddMonths(-3))
            });
        }

        /// <summary>
        /// 목록
        /// </summary>
        [HttpGet]
        public IActionResult List([FromQuery] PagingRequest req, [FromQuery] string siteId) {
            _logger.LogInformation(req.Dump());

            var query = _FilterAndSort(req);
            query = query.Where(x => x.IsUse == true && x.IsSysop == false);
            if (!string.IsNullOrEmpty(siteId)) {
                query = query.Where(x => x.SiteId == Util.ToInt(siteId));
            }
            var list = query.Select(emp => new {
                emp.SiteId,
                emp.UserId,
                emp.UserGroupId,
                emp.CompanyId,
                CmCompany = new {
                    emp.CmCompany.Name,
                    emp.CmCompany.CompanyTypeId,
                    CmCompanyType = new {
                        emp.CmCompany.CmCompanyType.Name
                    }
                },
                CmDepartment = new {
                    emp.CmDepartment.Name,
                    emp.CmDepartment.DepartmentId
                },
                emp.PositionId,
                CmPosition = new {
                    emp.CmPosition.Name
                },
                emp.BusinessFieldId,
                CmBusinessField = new {
                    emp.CmBusinessField.Name
                },
                emp.Name,
                emp.MobilePhoneNo,
                emp.OfficePhoneNo,
                emp.Email,
                emp.EnterDate,
                //UserGroupName = emp.CmUserGroup.Name,
                emp.AccessToken,
                CmFile = _storage.ParseFile(emp.CmFile),
            });
            var paging = PagingList.Pagination(list, req.page, req.limit);
            return Ok(paging);
        }

        // 엑셀 다운로드
        [AllowAnonymous]
        [HttpGet("excel")]
        public IActionResult ExportExcel([FromQuery] PagingRequest req, [FromQuery] string mapping) {
            var query = _FilterAndSort(req);

            var stream = new MemoryStream();

            using (var package = new ExcelPackage(stream)) {
                var workSheet = package.Workbook.Worksheets.Add("Sheet1");
                workSheet.Cells.LoadFromCollection(query, true);
                package.Save();
            }
            stream.Position = 0;
            string excelName = $"UserList-{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.xlsx";

            //return File(stream, "application/octet-stream", excelName);  
            return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", excelName);
        }

        /// <summary>
        /// 상세조회
        /// </summary>

        [HttpGet("[action]")]
        public IActionResult GetByUserId([FromQuery] string siteId, [FromQuery] string userId) {
            var emp = _service.GetByUserId(userId);

            if (emp == null)
                return NotFound();

            //return Ok(emp);
            return Ok(new {
                emp.UserId,
                emp.Passwd,
                emp.CompanyId,
                CompanyName = emp.CmCompany?.Name,
                emp.DepartmentId,
                DepartmentName = emp.CmDepartment?.Name,
                emp.PositionId,
                PositionName = emp.CmPosition?.Name,
                emp.BusinessFieldId,
                BusinessFieldName = emp.CmBusinessField?.Name,
                emp.UserGroupId,
                emp.Name,
                emp.EmploymentType,
                emp.EmploymentStatus,
                emp.MobilePhoneNo,
                emp.HomePhoneNo,
                emp.OfficePhoneNo,
                emp.Comment,
                emp.Email,
                emp.EnterDate,
                emp.RetireDate,
                emp.Certificated, //자격증
                emp.IsScheduleUser, //제어스케쥴담당자
                emp.IsSi, //SI접근권한
                emp.IsMobile, //모바일접근권한
                emp.IsUse,
                CmFile = _storage.ParseFile(emp.CmFile),
                CmFile1 = _storage.ParseFile(emp.CmFile1),
                //UserGroupName = emp.CmUserGroup.Name,
                //emp.AccessToken,
            });
        }


        /// <summary>
        /// 저장
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost("[action]")]
        public IActionResult Save([FromBody] CmUser data) {
            _logger.LogInformation("Save");
            //_logger.LogInformation(data.Dump());

            if (ModelState.IsValid) {
                _service.Save(data);
            } else {
                return BadRequest(ModelState);
            }
            return Ok();
        }
        [HttpDelete("{siteId}/{userId}")]
        public IActionResult Delete(int siteId, string userId) {
            _service.Delete(siteId, userId);
            return Ok();
        }

        [HttpPost("[action]")]
        public IActionResult UpdatePushToken([FromBody] CmUser data) {
            _service.UpdatePushToken(data);
            return Ok();
        }

        // Role 제한 테스트
        [AllowAnonymous]
        [HttpGet("auth")]
        public IActionResult Auth() {

            return Ok();
        }

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

            // 기본 Entity 검색
            query = query.Filter(req.conditions);
            // 기본 Entity 정렬
            query = query.Sort(req.sort);
            return query;
        }

    }
}