using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks;
using IRaCIS.Application.Services;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Application.Service.Inspection.Interface;
using IRaCIS.Core.Domain.Models;

namespace IRaCIS.Core.API.Controllers.Special
{
    //谨慎修改 涉及到财务模块

    [ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
    public class FinancialChangeController : ControllerBase
    {
        private readonly ITrialService _trialService;
        private readonly ICalculateService _calculateService;
        private readonly IInspectionService _inspectionService;

        public FinancialChangeController(ITrialService trialService, ICalculateService calculateService,
              IInspectionService inspectionService
            )
        {
            _trialService = trialService;
            _calculateService = calculateService;
            this._inspectionService = inspectionService;
        }


        //[TrialAudit(AuditType.TrialAudit, AuditOptType.AddOrUpdateTrial)]

        /// <summary> 添加实验项目-返回新增Id[AUTH]</summary>
        /// <returns>新记录Id</returns>
        [HttpPost, Route("Inspection/trial/addOrUpdateTrial")]
        [UnitOfWork]

        public async Task<IResponseOutput> AddOrUpdateTrialInspection(DataInspectionDto<TrialCommand> opt)
        {
            var fun =await AddOrUpdateTrial(opt.OptCommand);
            opt.AuditInfo.TrialId = fun.Data.Id;
            opt.AuditInfo.TrialName = fun.Data.ExperimentName;
            opt.AuditInfo.ResearchProgramNo = fun.Data.ResearchProgramNo;
            return await _inspectionService.Enforcement(opt.OptCommand, opt.AuditInfo, opt.SignInfo,null, fun);
        }


        /// <summary> 添加实验项目-返回新增Id[AUTH]</summary>
        /// <param name="param"></param>
        /// <returns>新记录Id</returns>
        [HttpPost, Route("trial/addOrUpdateTrial")]
       
        public async Task<IResponseOutput<Trial>>  AddOrUpdateTrial(TrialCommand param)
        {
            var userId = Guid.Parse(User.FindFirst("id").Value);
            var result = await _trialService.AddOrUpdateTrial(param);

            if (_trialService.TrialExpeditedChange)
            {
                var needCalReviewerIds = await _trialService.GetTrialEnrollmentReviewerIds(param.Id.Value);
                var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);

                calcList.ForEach(t =>
                {
                    if (needCalReviewerIds.Contains(t.DoctorId))
                    {
                        _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                        {
                            NeedCalculateReviewers = new List<Guid>()
                            {
                                t.DoctorId
                            },
                            CalculateMonth = DateTime.Parse(t.YearMonth)
                        }, User.FindFirst("id").Value);

                    }
                });
            }

            return result;
        }


        /// <summary>
        /// 添加或更新工作量[AUTH]
        /// </summary>
        /// <param name="_trialWorkloadService"></param>
        /// <param name="workLoadAddOrUpdateModel"></param>
        /// <returns></returns>
        
        [HttpPost, Route("doctorWorkload/workLoadAddOrUpdate")]
        [TypeFilter(typeof(TrialResourceFilter))]
        public async Task<IResponseOutput> WorkLoadAddOrUpdate([FromServices] IDoctorWorkloadService _trialWorkloadService, WorkloadCommand workLoadAddOrUpdateModel)
        {
            var userId = Guid.Parse(User.FindFirst("id").Value);
            var result = await _trialWorkloadService.AddOrUpdateWorkload(workLoadAddOrUpdateModel, userId);
            if (result.IsSuccess && workLoadAddOrUpdateModel.DataFrom == 2)
            {
                await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                {
                    NeedCalculateReviewers = new List<Guid>()
                    {
                        workLoadAddOrUpdateModel.DoctorId
                    },
                    CalculateMonth = workLoadAddOrUpdateModel.WorkTime
                }, User.FindFirst("id").Value);
            }
            return result;
        }


        
        [HttpDelete, Route("doctorWorkload/deleteWorkLoad/{id:guid}/{trialId:guid}")]
        [TypeFilter(typeof(TrialResourceFilter))]
        public async Task<IResponseOutput> DeleteWorkLoad([FromServices] IDoctorWorkloadService _trialWorkloadService, Guid id)
        {
            //先判断该工作量的费用是否被锁定,如果被锁定,则不能删除
            var workload = await _trialWorkloadService.GetWorkloadDetailById(id);
            var yearMonth = workload.WorkTime.ToString("yyyy-MM");
            var isLock = await _calculateService.IsLock(workload.DoctorId, yearMonth);

            if (isLock)
            {
                return ResponseOutput.NotOk("Expenses have been settled and workload can not be reset.");
            }

            var deleteResult = await _trialWorkloadService.DeleteWorkload(id);
            if (workload.DataFrom == (int)Domain.Share.WorkLoadFromStatus.FinalConfirm)
            {
                await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                {
                    NeedCalculateReviewers = new List<Guid>()
                    {
                        workload.DoctorId
                    },
                    CalculateMonth = workload.WorkTime
                }, User.FindFirst("id").Value);
            }
            return deleteResult;
        }


        /// <summary>
        /// 添加或更新汇率(会触发没有对锁定的费用计算)
        /// </summary>
        
        [HttpPost, Route("exchangeRate/addOrUpdateExchangeRate")]
        public async Task<IResponseOutput> AddOrUpdateExchangeRate([FromServices] IExchangeRateService _exchangeRateService, [FromServices] IPaymentAdjustmentService _costAdjustmentService, ExchangeRateCommand addOrUpdateModel)
        {
            var result = await _exchangeRateService.AddOrUpdateExchangeRate(addOrUpdateModel);
            var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, addOrUpdateModel.YearMonth);
            foreach (var item in calcList)
            {
                if (item != null)
                {
                   await  _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                    {
                        NeedCalculateReviewers = new List<Guid>()
                        {
                            item.DoctorId
                        },
                        CalculateMonth = DateTime.Parse(item.YearMonth)
                    }, User.FindFirst("id").Value);
                }
            }
           await _costAdjustmentService.CalculateCNY(addOrUpdateModel.YearMonth, addOrUpdateModel.Rate);
            return result;
        }


        /// <summary>
        /// 添加或更新 职称单价[AUTH]
        /// </summary>
        
        [HttpPost, Route("rankPrice/addOrUpdateRankPrice")]
        public async Task<IResponseOutput> AddOrUpdateRankPrice([FromServices] IReviewerPayInfoService _reviewerPayInfoService, [FromServices] IRankPriceService _rankPriceService, RankPriceCommand addOrUpdateModel)
        {
            if (addOrUpdateModel.Id != Guid.Empty && addOrUpdateModel.Id != null)
            {
                var needCalReviewerIds =await _reviewerPayInfoService.GetReviewerIdByRankId(Guid.Parse(addOrUpdateModel.Id.ToString()));
                var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);

                foreach (var item in calcList)
                {
                    if (item != null && needCalReviewerIds.Contains(item.DoctorId))
                    {
                        await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                        {
                            NeedCalculateReviewers = new List<Guid>()
                            {
                                item.DoctorId
                            },
                            CalculateMonth = DateTime.Parse(item.YearMonth)
                        }, User.FindFirst("id").Value);
                    }
                }
            }
            var userId = Guid.Parse(User.FindFirst("id").Value);
            return await _rankPriceService.AddOrUpdateRankPrice(addOrUpdateModel, userId);
        }



        /// <summary>
        /// 添加或更新(替换)医生支付展信息[AUTH]
        /// </summary>
        
        [HttpPost, Route("reviewerPayInfo/addOrUpdateReviewerPayInfo")]
        public async Task<IResponseOutput> AddOrUpdateReviewerPayInfo([FromServices] IReviewerPayInfoService _doctorPayInfoService, ReviewerPayInfoCommand addOrUpdateModel)
        {
            var userId = Guid.Parse(User.FindFirst("id").Value);
            var result =await _doctorPayInfoService.AddOrUpdateReviewerPayInfo(addOrUpdateModel, userId);
            var calcList = await _calculateService.GetNeedCalculateReviewerList(addOrUpdateModel.DoctorId, string.Empty);
            foreach (var item in calcList)
            {
                if (item != null)
                {
                    await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                    {
                        NeedCalculateReviewers = new List<Guid>()
                        {
                            item.DoctorId
                        },
                        CalculateMonth = DateTime.Parse(item.YearMonth)
                    }, User.FindFirst("id").Value);
                }
            }
            return result;
        }



        /// <summary>
        /// 保存(替换)项目支付价格信息(会触发没有被锁定的费用计算)[AUTH]
        /// </summary>
        
        [HttpPost, Route("trialPaymentPrice/addOrUpdateTrialPaymentPrice")]
        public async Task<IResponseOutput> AddOrUpdateTrialPaymentPrice([FromServices] ITrialPaymentPriceService _trialPaymentPriceService, TrialPaymentPriceCommand addOrUpdateModel)
        {
            var userId = Guid.Parse(User.FindFirst("id").Value);
            var result =await _trialPaymentPriceService.AddOrUpdateTrialPaymentPrice(addOrUpdateModel);
            var needCalReviewerIds = await _trialService.GetTrialEnrollmentReviewerIds(addOrUpdateModel.TrialId);
            var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);

            foreach (var item in calcList)
            {
                if (item != null && needCalReviewerIds.Contains(item.DoctorId))
                {
                   await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                    {
                        NeedCalculateReviewers = new List<Guid>()
                        {
                            item.DoctorId
                        },
                        CalculateMonth = DateTime.Parse(item.YearMonth)
                    }, User.FindFirst("id").Value);
                }
            }
            return result;
        }

        /// <summary>
        /// 批量更新奖励费用[AUTH]
        /// </summary>
        
        [HttpPost, Route("volumeReward/addOrUpdatevolumeRewardPriceList")]
        public async Task<IResponseOutput> AddOrUpdateAwardPriceList([FromServices] IVolumeRewardService _volumeRewardService, IEnumerable<AwardPriceCommand> addOrUpdateModel)
        {

            var result =await _volumeRewardService.AddOrUpdateVolumeRewardPriceList(addOrUpdateModel);

            var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
            foreach (var item in calcList)
            {
                if (item != null)
                {
                    await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
                    {
                        NeedCalculateReviewers = new List<Guid>()
                        {
                            item.DoctorId
                        },
                        CalculateMonth = DateTime.Parse(item.YearMonth)
                    }, User.FindFirst("id").Value);
                }
            }
            return result;
        }



        /// <summary>
        /// 计算医生月度费用,并将计算的结果存入费用表
        /// </summary>
        [HttpPost, Route("financial/calculateMonthlyPayment")]
        public async Task<IResponseOutput> CalculateMonthlyPayment(CalculateDoctorAndMonthDTO param)
        {
            if (!ModelState.IsValid)
            {
                return ResponseOutput.NotOk("Invalid parameter.");
            }
            return await _calculateService.CalculateMonthlyPayment(param, User.FindFirst("id").Value);
        }

        /// <summary>
        /// Financials /Monthly Payment 列表查询接口
        /// </summary>
        [HttpPost, Route("financial/getMonthlyPaymentList")]
        public async Task<IResponseOutput<PaymentDTO>> GetMonthlyPaymentList([FromServices] IPaymentService _paymentService, [FromServices] IExchangeRateService _exchangeRateService, MonthlyPaymentQueryDTO queryParam)
        {
            return ResponseOutput.Ok(new PaymentDTO
            {
                CostList = await _paymentService.GetMonthlyPaymentList(queryParam),
                ExchangeRate = await _exchangeRateService.GetExchangeRateByMonth(queryParam.StatisticsDate.ToString("yyyy-MM"))
            });
        }


    }
}