using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Performance.DtoModels.Request;
using System.IO;
using Microsoft.AspNetCore.StaticFiles;

namespace Performance.Api.Controllers
{
    [Route("api/[controller]")]
    public class ComputeController : Controller
    {
        private ComputeService _computeService;
        private AllotService _allotService;
        private ClaimService _claim;
        private EmployeeService _employeeService;
        private readonly DownloadService downloadService;

        public ComputeController(AllotService allotService,
            ComputeService computeService,
            EmployeeService employeeService,
            DownloadService downloadService,
            ClaimService claim)
        {
            _allotService = allotService;
            _computeService = computeService;
            _employeeService = employeeService;
            this.downloadService = downloadService;
            _claim = claim;
        }

        /// <summary>
        /// 获取绩效发放列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("getcompute")]
        [HttpPost]
        public ApiResponse GetCompute([CustomizeValidator(RuleSet = "Select"), FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetCompute(request.AllotId, request.Type);
            return new ApiResponse(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 特殊科室发放列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("getspecial")]
        [HttpPost]
        public ApiResponse<List<res_specialunit>> GetSpecial([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetSpecial(request.AllotId);
            return new ApiResponse<List<res_specialunit>>(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 医生组科室绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("getdoctordata")]
        [HttpPost]
        public ApiResponse<List<DeptResponse>> GetDoctor([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetDoctorPerformance(request.AllotId);
            return new ApiResponse<List<DeptResponse>>(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 护理组科室绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("getnursedata")]
        [HttpPost]
        public ApiResponse<List<DeptResponse>> GetNurse([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetNursePerformance(request.AllotId);
            return new ApiResponse<List<DeptResponse>>(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 其他组科室绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("getotherdata")]
        [HttpPost]
        public ApiResponse<List<DeptResponse>> GetOther([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetOtherPerformance(request.AllotId);
            return new ApiResponse<List<DeptResponse>>(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 行政科室绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("getofficedata")]
        [HttpPost]
        public ApiResponse<List<DeptResponse>> GetOffice([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetOfficePerformance(request.AllotId);
            return new ApiResponse<List<DeptResponse>>(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 返回院领导、中层、工勤组绩效
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("gethosdata")]
        [HttpPost]
        public ApiResponse<List<DeptResponse>> GetAdminPerformance([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetAdminPerformance(request.AllotId);
            return new ApiResponse<List<DeptResponse>>(ResponseType.OK, "ok", list);
        }


        /// <summary>
        /// 科室绩效详情
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("deptdetail")]
        [HttpPost]
        public ApiResponse DeptDetail([FromBody] DeptDetailRequest request)
        {
            ag_secondallot second = null;
            if (request.AccountID == 0)
            {
                if (request.SecondId == 0)
                    return new ApiResponse(ResponseType.ParameterError, "参数 AccountID或SecondId 无效");
                else
                {
                    second = _computeService.GetAccountId(request.SecondId, out int accountId);
                    request.AccountID = accountId;
                }
            }
            else if (request.AccountID != 0 && request.UnitType == (int)UnitType.特殊核算组)
            {
                second = _computeService.GetSecondByAccountId(request.AccountID);
            }
            else if (request.AccountID != 0 && request.UnitType == (int)UnitType.行政后勤)
            {
                var response = _computeService.DeptOfficeDetail(request.AccountID);
                return new ApiResponse(ResponseType.OK, response);
            }

            if (second != null && second.UnitType == UnitType.特殊核算组.ToString())
            {
                var response = _computeService.SpecialDeptDetail(second);
                return new ApiResponse(ResponseType.OK, response);
            }
            else if (second != null && second.UnitType == UnitType.行政后勤.ToString())
            {
                var response = _computeService.DeptOfficeDetail(request.AccountID);
                return new ApiResponse(ResponseType.OK, response);
            }
            else
            {
                var response = _computeService.DeptDetail(request.AccountID);
                return new ApiResponse(ResponseType.OK, response);
            }
        }

        /// <summary>
        /// 获取全院绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allcompute")]
        [HttpPost]
        public ApiResponse AllCompute([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var isShowManage = _computeService.IsShowManage(request.AllotId);
            //var list = isShowManage == 1
            //    ? _computeService.AllCompute(request.AllotId)
            //    : _computeService.AllManageCompute(request.AllotId);

            var list = _computeService.AllCompute(request.AllotId, allot.HospitalId, isShowManage);
            return new ApiResponse(ResponseType.OK, "ok", list);
        }


        /// <summary>
        /// 获取全院绩效平均
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allavg")]
        [HttpPost]
        public ApiResponse AllComputeAvg([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            List<res_baiscnorm> avgs = new List<res_baiscnorm>();
            var isShowManage = _computeService.IsShowManage(request.AllotId);
            var list = _computeService.AllCompute(request.AllotId, allot.HospitalId, isShowManage);

            if (list != null)
            {
                avgs = _computeService.AllComputeAvg(request.AllotId, list);
            }

            //List<res_baiscnorm> avgs = new List<res_baiscnorm>();
            //avgs.Add(new res_baiscnorm
            //{
            //    PositionName = "不含行政高层人均绩效",
            //    TotelNumber = gc.Select(w => new { w.JobNumber, w.EmployeeName }).Distinct().Count(),
            //    TotelValue = Math.Round(gc.Sum(s => s.RealGiveFee) ?? 0),
            //    AvgValue = gc.Select(p => new { p.JobNumber, p.EmployeeName }).Distinct().Count() == 0 
            //        ? 0 : Math.Round(gc.Sum(s => s.RealGiveFee) / gc.Select(p => new { p.JobNumber, p.EmployeeName }).Distinct().Count() ?? 0)
            //});

            //avgs.AddRange(
            //    list.GroupBy(w => w.UnitType).Select(w => new res_baiscnorm
            //    {
            //        PositionName = $"{w.Key}人均绩效",
            //        TotelNumber = w.Count(),
            //        TotelValue = Math.Round(w.Sum(s => s.RealGiveFee) ?? 0),
            //        AvgValue = gc.Select(p => new { p.JobNumber, p.EmployeeName }).Distinct().Count() == 0
            //            ? 0 : Math.Round(gc.Sum(s => s.RealGiveFee) / gc.Select(p => new { p.JobNumber, p.EmployeeName }).Distinct().Count() ?? 0)
            //    }));

            return new ApiResponse(ResponseType.OK, "ok", avgs.Select(w => new { w.ID, w.PositionName, w.TotelNumber, w.TotelValue, w.AvgValue }));
        }

        /// <summary>
        /// 获取全院管理绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allcompute/management")]
        [HttpPost]
        public ApiResponse AllManageCompute([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.AllCompute(request.AllotId, allot.HospitalId, 1);
            return new ApiResponse(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 获取全院绩效列表（人事科）
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allcompute/personnel")]
        [HttpPost]
        public ApiResponse AllComputeByPM([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var isShowManage = _computeService.IsShowManage(request.AllotId);

            var list = _computeService.AllCompute(request.AllotId, allot.HospitalId, isShowManage, true);
            if (list == null || !list.Any())
                return new ApiResponse(ResponseType.OK, "ok", list);

            var result = _computeService.ComputerGroupBy(list);
            return new ApiResponse(ResponseType.OK, "ok", result);
        }



        /// <summary>
        /// 修改实发绩效
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("updatereal")]
        [HttpPost]
        public ApiResponse UpdateRealfee([CustomizeValidator(RuleSet = "UpdateReal"), FromBody] ComputerRequest request)
        {
            var userId = _claim.GetUserId();
            var realName = _claim.GetUserClaim(JwtClaimTypes.RealName);
            var compute = _computeService.GetComputeSingle(request.ComputeId);
            if (null == compute)
                throw new PerformanceException("当前数据记录不存在");
            compute = _computeService.UpdateRealfee(request, userId, realName);
            return new ApiResponse(ResponseType.OK, "修改成功", compute);
        }

        /// <summary>
        /// 获取全院绩效列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("getbaiscnorm")]
        [HttpPost]
        public ApiResponse GetBaiscnorm([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetBaiscnorm(request.AllotId);
            return new ApiResponse(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 医生绩效详情
        /// </summary>
        /// <param name="computeId"></param>
        /// <returns></returns>
        [Route("doctordetail/{computeId}")]
        [HttpPost]
        public ApiResponse DoctorDetail(int computeId)
        {
            var result = _computeService.GetDoctorDetail(computeId);
            return new ApiResponse(ResponseType.OK, result);
        }

        #region 人均绩效修改

        /// <summary>
        /// 编辑全院绩效平均
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("EditHospitalAvg")]
        [HttpPost]
        public ApiResponse<res_baiscnorm> EditHospitalAvg([FromBody] ComputerAvgRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            var result = _computeService.EditHospitalAvg(request);

            return new ApiResponse<res_baiscnorm>(ResponseType.OK, result);
        }

        #endregion

        /// <summary>
        /// 自定义列头
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("customcolumnheaders")]
        [HttpPost]
        public ApiResponse CustomColumnHeaders([FromBody] ComputerAliasRequest request)
        {
            var result = _computeService.CustomColumnHeaders(request.HospitalId, request.Route);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 全院绩效进行批次标记
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allcompute/batch")]
        [HttpPost]
        public ApiResponse Batch([FromBody] BatchRequest request)
        {
            var result = _computeService.Batch(request);
            return result ? new ApiResponse(ResponseType.OK, "操作成功") : new ApiResponse(ResponseType.Fail, "操作失败");
        }

        #region 发放表下载

        /// <summary>
        /// 下载院领导、中层、工勤组绩效
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        [Route("gethosdata/download/{allotId}")]
        [HttpPost]
        public IActionResult GetAdminPerDownload(int allotId)
        {
            var allot = _allotService.GetAllot(allotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var list = _computeService.GetAdminPerformance(allotId);

            var filepath = downloadService.DeptReport(allotId, list);

            var memoryStream = new MemoryStream();
            using (var stream = new FileStream(filepath, FileMode.Open))
            {
                stream.CopyToAsync(memoryStream).Wait();
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            var provider = new FileExtensionContentTypeProvider();
            FileInfo fileInfo = new FileInfo(filepath);
            var memi = provider.Mappings[".xlsx"];
            return File(memoryStream, memi, Path.GetFileName(fileInfo.Name));
        }

        /// <summary>
        /// 下载全院绩效列表
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        [Route("allcompute/download/{allotId}")]
        [HttpPost]
        public IActionResult AllComputeDownload(int allotId)
        {
            var allot = _allotService.GetAllot(allotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var isShowManage = _computeService.IsShowManage(allotId);

            var list = _computeService.AllCompute(allotId, allot.HospitalId, isShowManage);

            var filepath = downloadService.AllComputerReport(allotId, list, true, "全院绩效发放");

            var memoryStream = new MemoryStream();
            using (var stream = new FileStream(filepath, FileMode.Open))
            {
                stream.CopyToAsync(memoryStream).Wait();
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            var provider = new FileExtensionContentTypeProvider();
            FileInfo fileInfo = new FileInfo(filepath);
            var memi = provider.Mappings[".xlsx"];
            return File(memoryStream, memi, Path.GetFileName(fileInfo.Name));
        }

        /// <summary>
        /// 下载全院绩效列表（人事科）
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        [Route("allcompute/personnel/download/{allotId}")]
        [HttpPost]
        public IActionResult AllComputeByPMDownLoad(int allotId)
        {
            var allot = _allotService.GetAllot(allotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");
            var isShowManage = _computeService.IsShowManage(allotId);

            var list = _computeService.AllCompute(allotId, allot.HospitalId, isShowManage, true);


            var result = _computeService.ComputerGroupBy(list);
            var filepath = downloadService.AllComputerReport(allotId, result, false, "财务全院绩效");

            var memoryStream = new MemoryStream();
            using (var stream = new FileStream(filepath, FileMode.Open))
            {
                stream.CopyToAsync(memoryStream).Wait();
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            var provider = new FileExtensionContentTypeProvider();
            FileInfo fileInfo = new FileInfo(filepath);
            var memi = provider.Mappings[".xlsx"];
            return File(memoryStream, memi, Path.GetFileName(fileInfo.Name));
        }
        #endregion

        #region 发放表视图、下载


        /// <summary>
        /// 全院核算绩效发放（视图）
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("gethosdataView")]
        [HttpPost]
        public ApiResponse GethosdataView([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            var list = _computeService.GetAllComputeView(allot.HospitalId, request.AllotId, "view_allot_sign_dept");
            return new ApiResponse(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 全院核算绩效发放（视图） 下载
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        [Route("gethosdataView/download/{allotId}")]
        [HttpPost]
        public IActionResult GethosdataView(int allotId)
        {
            var allot = _allotService.GetAllot(allotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            var list = _computeService.GetAllComputeView(allot.HospitalId, allotId, "view_allot_sign_dept");
            var filepath = downloadService.AllComputerViewReport(allotId, list, "/result/print/compute", "全院核算绩效发放");

            var memoryStream = new MemoryStream();
            using (var stream = new FileStream(filepath, FileMode.Open))
            {
                stream.CopyToAsync(memoryStream).Wait();
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            var provider = new FileExtensionContentTypeProvider();
            FileInfo fileInfo = new FileInfo(filepath);
            var memi = provider.Mappings[".xlsx"];
            return File(memoryStream, memi, Path.GetFileName(fileInfo.Name));
        }

        /// <summary>
        /// 获取全院绩效列表（视图）
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allcomputeView")]
        [HttpPost]
        public ApiResponse AllComputeView([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            var list = _computeService.GetAllComputeView(allot.HospitalId, request.AllotId, "view_allot_sign_emp");
            return new ApiResponse(ResponseType.OK, "ok", list);
        }

        /// <summary>
        /// 下载全院绩效列表
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        [Route("allcomputeView/download/{allotId}")]
        [HttpPost]
        public IActionResult AllComputeViewDownload(int allotId)
        {
            var allot = _allotService.GetAllot(allotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            var list = _computeService.GetAllComputeView(allot.HospitalId, allotId, "view_allot_sign_emp");
            var filepath = downloadService.AllComputerViewReport(allotId, list, "/result/compute", "全院绩效发放");

            var memoryStream = new MemoryStream();
            using (var stream = new FileStream(filepath, FileMode.Open))
            {
                stream.CopyToAsync(memoryStream).Wait();
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            var provider = new FileExtensionContentTypeProvider();
            FileInfo fileInfo = new FileInfo(filepath);
            var memi = provider.Mappings[".xlsx"];
            return File(memoryStream, memi, Path.GetFileName(fileInfo.Name));
        }


        /// <summary>
        /// 获取全院绩效列表（人事科）
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("allcomputeView/personnel")]
        [HttpPost]
        public ApiResponse AllComputeViewByPM([FromBody] ComputerRequest request)
        {
            var allot = _allotService.GetAllot(request.AllotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            var result = _computeService.GetAllComputeView(allot.HospitalId, request.AllotId, "view_allot_sign_emp_finance");

            //var result = _computeService.ComputerGroupBy(list);
            return new ApiResponse(ResponseType.OK, "ok", result);
        }

        /// <summary>
        /// 下载全院绩效列表（人事科）
        /// </summary>
        /// <param name="allotId"></param>
        /// <returns></returns>
        [Route("allcomputeView/personnel/download/{allotId}")]
        [HttpPost]
        public IActionResult AllComputeByPMViewDownLoad(int allotId)
        {
            var allot = _allotService.GetAllot(allotId);
            if (null == allot)
                throw new PerformanceException("当前绩效记录不存在");

            var result = _computeService.GetAllComputeView(allot.HospitalId, allotId, "view_allot_sign_emp_finance");
            var filepath = downloadService.AllComputerViewReport(allotId, result, "/result/wholehospital", "财务全院绩效发放");

            var memoryStream = new MemoryStream();
            using (var stream = new FileStream(filepath, FileMode.Open))
            {
                stream.CopyToAsync(memoryStream).Wait();
            }
            memoryStream.Seek(0, SeekOrigin.Begin);
            var provider = new FileExtensionContentTypeProvider();
            FileInfo fileInfo = new FileInfo(filepath);
            var memi = provider.Mappings[".xlsx"];
            return File(memoryStream, memi, Path.GetFileName(fileInfo.Name));
            #endregion

        }
    }
}