using FluentValidation.AspNetCore;
using Hangfire;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace Performance.Api.Controllers
{
    [Route("api/[controller]")]
    public class AllotController : Controller
    {
        private AllotService _allotService;
        private HospitalService _hospitalService;
        private ConfigService _configService;
        private IHostingEnvironment _evn;
        private ILogger<AllotController> _logger;
        private ClaimService _claim;
        private readonly LogManageService logManageService;

        public AllotController(AllotService allotService,
            HospitalService hospitalService, ConfigService configService,
            ILogger<AllotController> logger, IHostingEnvironment evn,
            ClaimService claim, LogManageService logManageService)
        {
            _allotService = allotService;
            _hospitalService = hospitalService;
            _logger = logger;
            _evn = evn;
            _claim = claim;
            this.logManageService = logManageService;
            _configService = configService;
        }

        /// <summary>
        /// 绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("list")]
        [HttpPost]
        public ApiResponse List([FromBody] AllotRequest request)
        {
            List<AllotResponse> allots = _allotService.GetAllotList(request.HospitalId);
            return new ApiResponse(ResponseType.OK, allots);
        }

        /// <summary>
        /// 生成成功或归档绩效记录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("list/success")]
        [HttpPost]
        public ApiResponse Success([FromBody] AllotRequest request)
        {
            List<AllotResponse> allots = _allotService.GetSuccAllotList(request.HospitalId);
            return new ApiResponse(ResponseType.OK, allots);
        }

        /// <summary>
        /// 新增绩效
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("insert")]
        [HttpPost]
        public ApiResponse Insert([CustomizeValidator(RuleSet = "Insert"), FromBody] AllotRequest request)
        {
            var userId = _claim.GetUserId();
            var result = _allotService.InsertAllot(request, userId);
            _configService.Copy(result);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 修改绩效
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("update")]
        [HttpPost]
        public ApiResponse<AllotResponse> Update([CustomizeValidator(RuleSet = "Update"), FromBody] AllotRequest request)
        {
            var result = _allotService.UpdateAllot(request);
            return new ApiResponse<AllotResponse>(ResponseType.OK, result);
        }

        /// <summary>
        /// 删除绩效
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("delete")]
        [HttpPost]
        public ApiResponse Delete([CustomizeValidator(RuleSet = "Delete"), FromBody] AllotRequest request)
        {
            bool result = _allotService.DeleteAllot(request.ID);
            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [Route("import")]
        [HttpPost]
        public ApiResponse Import([FromForm] IFormCollection form)
        {
            var allotid = form.ToDictionary().GetValue("allotid", 0);
            if (allotid <= 0)
                return new ApiResponse(ResponseType.Fail, "参数错误", "allotid无效");

            var file = ((FormFileCollection)form.Files).FirstOrDefault();
            if (file == null)
                return new ApiResponse(ResponseType.Fail, "参数错误", "文件无效");

            var allot = _allotService.GetAllot(allotid);
            if (allot == null)
                return new ApiResponse(ResponseType.Fail, "allotid不存在");

            var name = FileHelper.GetFileNameNoExtension(file.FileName) + DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var ext = FileHelper.GetExtension(file.FileName);
            var dpath = Path.Combine(_evn.ContentRootPath, "Files", $"{allot.HospitalId}", $"{allot.Year}{allot.Month.ToString().PadLeft(2, '0')}");
            FileHelper.CreateDirectory(dpath);

            var path = Path.Combine(dpath, $"{name}{ext}");

            using (var stream = file.OpenReadStream())
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                if (!FileHelper.CreateFile(path, bytes))
                    return new ApiResponse(ResponseType.Fail, $"{file.FileName}上传失败");
                allot.Path = path;
                allot.States = (int)AllotStates.FileUploaded;
                allot.Remark = EnumHelper.GetDescription(AllotStates.FileUploaded);
                allot.UploadDate = DateTime.Now;
                allot.Generate = (int)AllotGenerate.Init;
                if (!_allotService.Update(allot))
                    return new ApiResponse(ResponseType.Fail, $"{file.FileName}上传成功，修改状态失败");
                _configService.Clear(allot.ID);
            }

            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 绩效生成
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("generate")]
        [HttpPost]
        public ApiResponse Generate([CustomizeValidator(RuleSet = "Delete"), FromBody] AllotRequest request)
        {
            var allot = _allotService.GetAllot(request.ID);
            if (null == allot || string.IsNullOrEmpty(allot.Path))
                throw new PerformanceException("当前绩效记录不存在或没有上传数据文件");
            var email = _claim.GetUserClaim(JwtClaimTypes.Mail);
            if (allot.States == (int)AllotStates.Wait)
                return new ApiResponse(ResponseType.OK, "当前绩效正在等待生成");

            logManageService.WriteMsg("生成绩效准备中", $"准备生成{allot.Year}-{allot.Month.ToString().PadLeft(2, '0')}月份绩效，请稍等!", 1, allot.ID, "ReceiveMessage", true);
            _allotService.UpdateAllotStates(allot.ID, (int)AllotStates.Wait, EnumHelper.GetDescription(AllotStates.Wait), allot.Generate);
            if (_evn.IsEnvironment("Localhost"))
                _allotService.Generate(allot, email);
            else
                BackgroundJob.Schedule(() => _allotService.Generate(allot, email), TimeSpan.FromSeconds(1));
            logManageService.WriteMsg("等待绩效生成", $"等待绩效生成{allot.Year}-{allot.Month.ToString().PadLeft(2, '0')}月份绩效!", 1, allot.ID, "ReceiveMessage");
            //_allotService.Generate(allot, email);
            ////BackgroundJob.Enqueue(() => _allotService.Generate(allot, email));
            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 归档绩效记录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("pigeonhole")]
        [HttpPost]
        public ApiResponse Pigeonhole([CustomizeValidator(RuleSet = "Delete"), FromBody] AllotRequest request)
        {
            var allot = _allotService.GetAllot(request.ID);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在或没有上传数据文件");
            _allotService.Pigeonhole(allot);
            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 归档时检索数据是否合格
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("checkrecord")]
        [HttpPost]
        public ApiResponse CheckRecord([CustomizeValidator(RuleSet = "Delete"), FromBody] AllotRequest request)
        {
            var allot = _allotService.GetAllot(request.ID);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在或没有上传数据文件");
            var list = _allotService.GetAgainAllotNotSucceed(allot);
            return new ApiResponse(ResponseType.OK, list);
        }


        /// <summary>
        /// 绩效校验结果
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allotcheckresult")]
        [HttpPost]
        public ApiResponse AllotCheckResult([CustomizeValidator(RuleSet = "Delete"), FromBody] AllotRequest request)
        {
            var allot = _allotService.GetAllot(request.ID);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _allotService.AllotCheckResult(allot);
            return new ApiResponse(ResponseType.OK, list);
        }

        /// <summary>
        /// 绩效历史日志
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allotlog")]
        [HttpPost]
        public ApiResponse AllotLog([CustomizeValidator(RuleSet = "Delete"), FromBody] AllotRequest request)
        {
            var allot = _allotService.GetAllot(request.ID);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _allotService.AllotLog(allot);
            return new ApiResponse(ResponseType.OK, list);
        }

        /// <summary>
        /// 绩效审核通过，绩效下发
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("issued")]
        [HttpPost]
        public ApiResponse Issued([FromBody] AllotRequest request)
        {
            var allot = _allotService.GetAllot(request.ID);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            _allotService.UpdateAllotStates(allot.ID, (int)AllotStates.GenerateSucceed, EnumHelper.GetDescription(AllotStates.GenerateSucceed));
            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 绩效详情计算公式显示/隐藏
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("update/showformula")]
        [HttpPost]
        public ApiResponse UpdateAllotShowFormula([FromBody] AllotRequest request)
        {
            if (request.ID < 1)
                return new ApiResponse(ResponseType.ParameterError, "绩效信息无效");
            var result = _allotService.UpdateAllotShowFormula(request.ID);
            return new ApiResponse(ResponseType.OK, result);
        }
    }
}
