using MapsterMapper;
using Microsoft.AspNetCore.Mvc;
using XF.Domain.Authentications;
using XF.Domain.Repository;
using Hotline.Application.Caselibrary;
using Hotline.Share.Dtos.Caselibrary;
using SqlSugar;
using Hotline.CaseLibrary;
using XF.Domain.Exceptions;
using Hotline.Share.Dtos;
using Hotline.Share.Tools;
using Hotline.Share.Enums.Caselibrary;
using Hotline.Application.ExportWord;
using Hotline.Application.Tools;
using Hotline.Share.Enums.Article;
using XF.Utility.EnumExtensions;
using Hotline.Share.Dtos.Order;
using Hotline.Application.ExportExcel;
using Hotline.Api.Filter;

namespace Hotline.Api.Controllers
{
    /// <summary>
    /// 案例库
    /// </summary>
    public class CaseController : BaseController
    {

        #region 注入

        private readonly IMapper _mapper;
        private readonly ISessionContext _sessionContext;
        private readonly ICaseApplication _caseApplication;
        private readonly IRepository<CaseType> _caseTypeRepository;
        private readonly IRepository<CaseList> _caseListRepository;
        private readonly IRepository<CaseCollect> _caseCollectRepository;
        private readonly IWordHelperService _wordHelperService;
        private readonly IExportApplication _exportApplication;


        public CaseController(
           IMapper mapper,
           ISessionContext sessionContext,
           ICaseApplication CaseApplication,
           IRepository<CaseType> CaseTypeRepository,
           IRepository<CaseList> CaseListRepository,
           IRepository<CaseCollect> CaseCollectRepository,
           IWordHelperService wordHelperService,
           IExportApplication exportApplication)
        {
            _mapper = mapper;
            _sessionContext = sessionContext;
            _caseApplication = CaseApplication;
            _caseTypeRepository = CaseTypeRepository;
            _caseListRepository = CaseListRepository;
            _caseCollectRepository = CaseCollectRepository;
            _wordHelperService = wordHelperService;
            _exportApplication = exportApplication;
        }

        #endregion

        #region 案例库类型管理

        /// <summary>
        /// 获取列表层级分类
        /// </summary>
        /// <param name="IsEnable">是否启用</param>
        /// <returns></returns>
        [HttpGet("type/treelist")]
        public async Task<List<CaseTypeDto>> QueryAllTreeList(bool? IsEnable)
        {
            return await _caseTypeRepository.Queryable()
                .WhereIF(IsEnable.HasValue, x => x.IsEnable == IsEnable)
                .Where(x => SqlFunc.Subqueryable<CaseTypeOrg>().Where(to => to.TypeId == x.Id).Any() ||
                SqlFunc.Subqueryable<CaseTypeOrg>().Where(to => to.TypeId == x.Id).NotAny()
                )
                .Select(x => new CaseTypeDto()
                {
                    Id = x.Id.SelectAll()
                }
                )
                .OrderBy(x => x.Sort).ToTreeAsync(it => it.children, it => it.ParentId, null, it => it.Id);
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("type/add")]
        public async Task<string> AddType([FromBody] AddCaseTypeDto dto)
        {
            return await _caseApplication.AddTypeAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("type/update")]
        public async Task UpdateType([FromBody] UpdateCaseTypeDto dto)
        {
            await _caseApplication.UpdateTypeAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 查询详情
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpGet("type/info/{Id}")]
        public async Task<CaseType> GetType(string Id)
        {
            var types = await _caseTypeRepository.Queryable()
                .Includes(x => x.CaseTypeOrgs)   // 填充子对象
                .Where(x => x.Id == Id)
                .FirstAsync(HttpContext.RequestAborted);
            if (types is null)
                throw UserFriendlyException.SameMessage("查询失败！");
            return types;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpDelete("type/remove/{Id}")]
        public async Task RemoveType(string Id)
        {
            await _caseApplication.RemoveTypeAsync(Id, HttpContext.RequestAborted);
        }

        #endregion

        #region 案例库管理

        /// <summary>
        /// 案例库分类列表
        /// </summary>
        /// <param name="IsEnable"></param>
        /// <returns></returns>
        [HttpGet("list/treelist")]
        public async Task<List<CaseTypeDto>> QueryAllCaseTypeTreeList(bool? IsEnable)
        {
            return await _caseTypeRepository.Queryable()
                .WhereIF(IsEnable.HasValue, x => x.IsEnable == IsEnable)
                .Where(x => SqlFunc.Subqueryable<CaseTypeOrg>().Where(to => to.TypeId == x.Id).Any() ||
                SqlFunc.Subqueryable<CaseTypeOrg>().Where(to => to.TypeId == x.Id).NotAny()
                )
                .Select(x => new CaseTypeDto()
                {
                    Id = x.Id.SelectAll(),
                    CaseNum = SqlFunc.Subqueryable<CaseRelationType>().LeftJoin<CaseList>((kr, k) => kr.CaseId == k.Id)
                         .Where((kr, k) => kr.CaseTypeId == x.Id)
                         .DistinctCount(kr => kr.CaseId)
                }
                )
                .OrderBy(x => x.Sort).ToTreeAsync(it => it.children, it => it.ParentId, null, it => it.Id);
        }

        /// <summary>
        /// 案例库列表
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet("list")]
        public async Task<PagedDto<CaseDataDto>> QueryAllCaseList([FromQuery] CaseListDto pagedDto)
        {
            return (await _caseApplication.QueryAllCaseListAsync(pagedDto, HttpContext.RequestAborted)).ToPaged();
        }

        /// <summary>
        /// 案例库草稿
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("list/draft")]
        public async Task<string> CaseDraft([FromBody] AddCaseListDto dto)
        {
            dto.Status = ECaseStatus.NewDrafts;
            return await _caseApplication.AddCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库草稿修改
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("list/draftupdate")]
        public async Task UpdateCaseDraft([FromBody] UpdateCaseListDto dto)
        {
            dto.Status = ECaseStatus.NewDrafts;
            await _caseApplication.UpdateCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库草稿上架到审核
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("list/draftadd")]
        public async Task AddCaseDraft([FromBody] UpdateCaseListDto dto)
        {
            dto.ApplyStatus = ECaseApplyStatus.Add;
            dto.Status = ECaseStatus.Auditing;
            await _caseApplication.UpdateCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库草稿删除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpDelete("list/draftremove/{Id}")]
        public async Task RemovePlanDraft(string Id)
        {
            UpdateCaseListDto dto = new UpdateCaseListDto();
            dto.ApplyStatus = ECaseApplyStatus.Delete;
            dto.Status = ECaseStatus.Auditing;
            dto.Id = Id;
            await _caseApplication.RemoveCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库删除
        /// </summary>
        /// <param name="dtoDel"></param>
        /// <returns></returns>
        [HttpDelete("list/remove")]
        public async Task RemovePlan([FromBody] DelCaseListDto dtoDel)
        {
            UpdateCaseListDto dto = new UpdateCaseListDto();
            dto.ApplyStatus = ECaseApplyStatus.Delete;
            dto.Status = ECaseStatus.Auditing;
            dto.Id = dtoDel.Id;
            dto.ApplyReason = dtoDel.ApplyReason;
            await _caseApplication.UpdateCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库新增到审核
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("list/add")]
        public async Task<string> AddCase([FromBody] AddCaseListDto dto)
        {
            dto.ApplyStatus = ECaseApplyStatus.Add;
            dto.Status = ECaseStatus.Auditing;
            return await _caseApplication.AddCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库编辑提交到审核
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("list/update")]
        public async Task UpdateCase([FromBody] UpdateCaseListDto dto)
        {
            dto.ApplyStatus = ECaseApplyStatus.Update;
            dto.Status = ECaseStatus.Auditing;
            await _caseApplication.UpdateCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库上架
        /// </summary>
        /// <param name="Id">案例库ID</param>
        /// <returns></returns>
        [HttpGet("list/onshelf/{Id}")]
        public async Task OnshelfPlan(string Id)
        {
            UpdateCaseListDto dto = new UpdateCaseListDto();
            dto.Id = Id;
            dto.ApplyStatus = ECaseApplyStatus.Add;
            dto.Status = ECaseStatus.OnShelf;
            dto.OnShelfTime = DateTime.Now;
            await _caseApplication.AuditCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库下架
        /// </summary>
        /// <param name="Id">案例库ID</param>
        /// <returns></returns>
        [HttpGet("list/offshelf/{Id}")]
        public async Task OffshelfCase(string Id)
        {
            UpdateCaseListDto dto = new UpdateCaseListDto();
            dto.Id = Id;
            dto.ApplyStatus = ECaseApplyStatus.Offshelf;
            dto.Status = ECaseStatus.Auditing;
            dto.OffShelfTime = DateTime.Now;

            await _caseApplication.AuditCaseAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 设置热门
        /// </summary>
        /// <param name="Ids"></param>
        /// <param name="Popular"></param>
        /// <returns></returns>
        [HttpPost("list/popular")]
        public async Task PopularCase([FromBody] CaseInfoPopularDto dto)
        {
            if (dto.Ids.Length > 0)
            {
                for (int i = 0; i < dto.Ids.Length; i++)
                {
                    var Case = await _caseListRepository.GetAsync(dto.Ids[i]);

                    //if (Case == null)
                    //    throw UserFriendlyException.SameMessage("案例库查询失败");
                    if (Case != null)
                    {
                        Case.IsPopular = dto.Popular;
                        await _caseListRepository.UpdateNullAsync(Case, HttpContext.RequestAborted);
                    }
                }
            }
        }

        /// <summary>
        /// 案例库审核（新增、修改、删除）
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("list/examin")]
        public async Task ExaminCase([FromBody] AuditCaseListDto dto)
        {
            var Case = await _caseListRepository.GetAsync(dto.Id);
            if (Case == null)
                throw UserFriendlyException.SameMessage("案例库查询失败");

            var CaseDto = _mapper.Map<UpdateCaseListDto>(Case);

            if (dto.State == 0)
            {//不同意
                CaseDto.Status = ECaseStatus.Revert;
            }
            else if (dto.State == 1)
            {//同意 
                if (CaseDto.ApplyStatus == ECaseApplyStatus.Add)
                {
                    CaseDto.Status = ECaseStatus.OnShelf;
                    CaseDto.OnShelfTime = DateTime.Now;
                }
                if (CaseDto.ApplyStatus == ECaseApplyStatus.Update)
                {
                    CaseDto.Status = ECaseStatus.OnShelf;
                    CaseDto.OnShelfTime = DateTime.Now;
                    CaseDto.UpdateTime = DateTime.Now;
                }
                if (CaseDto.ApplyStatus == ECaseApplyStatus.Offshelf)
                {
                    CaseDto.Status = ECaseStatus.OffShelf;
                    CaseDto.OffShelfTime = DateTime.Now;
                }
                if (CaseDto.ApplyStatus == ECaseApplyStatus.Delete)
                {
                    CaseDto.Status = ECaseStatus.Drafts;
                }
            }
            CaseDto.Id = dto.Id;
            CaseDto.ExaminTime = DateTime.Now;
            CaseDto.ExaminManId = _sessionContext.UserId;
            CaseDto.ExaminOrganizeId = _sessionContext.OrgId;
            CaseDto.ExaminOpinion = dto.ExaminOpinion;

            await _caseApplication.AuditCaseAsync(CaseDto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库详情
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="IsAddPv"></param>
        /// <returns></returns>
        [HttpGet("list/info")]
        public async Task<CaseInfoDto> GetCase(string Id, bool IsAddPv)
        {
            return await _caseApplication.GetCaseAsync(Id, IsAddPv, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 案例库申请理由
        /// </summary>
        /// <param name="Id">案例库ID</param>
        /// <returns></returns>
        [HttpGet("list/reason/{Id}")]
        public async Task<CaseApplyReasonDto> ReasonPlan(string Id)
        {
            var reason = await _caseListRepository.GetAsync(x => x.Id == Id);
            return _mapper.Map<CaseApplyReasonDto>(reason);
        }

        /// <summary>
        /// 案例库评分
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("list/score")]
        public async Task ScoreCase([FromBody] PvCaseListDto dto)
        {
            var collect = await _caseCollectRepository.GetAsync(x => x.CaseId == dto.Id && x.CreatorId == _sessionContext.UserId);
            if (collect != null)
            {
                if (collect.Score > 0)
                    throw UserFriendlyException.SameMessage("当前知识已经评分");

                collect.Score = dto.Score;
                await _caseCollectRepository.UpdateAsync(collect, HttpContext.RequestAborted);
            }
            else
            {
                collect = new CaseCollect();
                collect.CaseId = dto.Id;
                collect.Score = dto.Score;
                await _caseCollectRepository.AddAsync(collect, HttpContext.RequestAborted);
            }

            //计算总分
            var sugar = _caseCollectRepository.Queryable().Where(x => x.CaseId == dto.Id);
            var count = await sugar.CountAsync();
            var collects = await sugar.SumAsync(x => x.Score);
            var scoreTemp = collects / count;
            var Case = await _caseListRepository.GetAsync(x => x.Id == dto.Id);
            if (Case != null)
            {
                Case.Score = decimal.Round(scoreTemp.Value, 1);
                await _caseListRepository.UpdateAsync(Case, HttpContext.RequestAborted);
            }
        }

        /// <summary>
        /// 案例库查重
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("list/exist")]
        public async Task<bool> ExistCase([FromBody] CaseExistDto dto)
        {
            var any = await _caseListRepository.Queryable()
                .Where(x => x.Status == ECaseStatus.Auditing || x.Status >= ECaseStatus.OnShelf)
                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Equals(dto.Title))
                .WhereIF(!string.IsNullOrEmpty(dto.Abstract), x => x.Abstract.Equals(dto.Abstract))
                .WhereIF(!string.IsNullOrEmpty(dto.Describe), x => x.Describe.Equals(dto.Describe))
                .WhereIF(!string.IsNullOrEmpty(dto.Result), x => x.Result.Equals(dto.Result))
                .WhereIF(!string.IsNullOrEmpty(dto.Reason), x => x.Reason.Equals(dto.Reason))
                .WhereIF(!string.IsNullOrEmpty(dto.Id), x => x.Id != dto.Id)
                .AnyAsync();
            return any;
        }

        /// <summary>
        /// 案例库详情导出
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("list/info/export")]
		[LogFilterAlpha("导出日志")]
		public async Task<IActionResult> CaseInfoExport([FromBody] CaseInfoExportDto dto)
        {
            if (dto.Ids.Length > 1)
            {
                var streams = await _caseApplication.CaseInfoListExportAsync(dto, HttpContext.RequestAborted);
                byte[] fileBytes = _wordHelperService.ConvertZipStream(streams);
                var name = DateTime.Now.ToString("yyyyMMddHHmmss");
                return File(fileBytes, "application/octet-stream", $"{name}.zip");
            }
            var info = await _caseListRepository.GetAsync(dto.Ids[0]) ?? throw UserFriendlyException.SameMessage("案例不存在");
            return info.Result.HtmlToStream(dto.FileType).GetFileStreamResult(dto.FileType, info.Title, false);
        }

        /// <summary>
        /// 案例库列表导出
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("export")]
        public async Task<IActionResult> GetPlanListExportAsync([FromBody] ExportExcelDto<CaseListDto> dto)
        {
            var items = (await _caseApplication.QueryAllCaseListAsync(dto.QueryDto, HttpContext.RequestAborted)).Item2;
            return _exportApplication.GetExcelFile(dto, items, "案例明细导出");
        }

        /// <summary>
        /// 案例库列表页面枚举值
        /// </summary>
        /// <returns></returns>
        [HttpGet("list/status-data")]
        public Dictionary<string, dynamic> PlanStatus()
        {
            var tabStatusName = new List<KeyValuePair<int, string>>
            {
                new KeyValuePair<int, string>(3, "已上架"),
                new KeyValuePair<int, string>(4, "已下架"),
                new KeyValuePair<int, string>(1, "审核中"),
                new KeyValuePair<int, string>(7, "草稿"),
                new KeyValuePair<int, string>(-1, "全部")
            };

            var tabExamineName = new List<KeyValuePair<int, string>>
            {
                new KeyValuePair<int, string>(-1, "全部"),
                new KeyValuePair<int, string>(0, "新增审核"),
                new KeyValuePair<int, string>(1, "修改审核"),
                new KeyValuePair<int, string>(2, "删除审核")
            };

            var StatusName = new List<KeyValuePair<int, string>>
            {
                new KeyValuePair<int, string>(-1, "全部"),
                new KeyValuePair<int, string>(0, "待提交"),
                new KeyValuePair<int, string>(1, "审核中"),
                new KeyValuePair<int, string>(3, "已上架"),
                new KeyValuePair<int, string>(4, "已下架"),
                new KeyValuePair<int, string>(5, "审核不通过"),
                new KeyValuePair<int, string>(6, "已过期"),
                new KeyValuePair<int, string>(7, "草稿")
            };

            var ApplyStatusName = new List<KeyValuePair<int, string>>
            {
                new KeyValuePair<int, string>(-1, "全部"),
                new KeyValuePair<int, string>(0, "新增审核"),
                new KeyValuePair<int, string>(1, "修改审核"),
                new KeyValuePair<int, string>(2, "删除审核")
            };

            var ignoreFileType = EFileType.excel | EFileType.pdf;
            var items = EnumExts.GetDescriptions<EFileType>();
            var filteredDictionary = items
                 .Where(kvp => (ignoreFileType & (EFileType)kvp.Key) == 0)
                 .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
                 .ToList();

            return new Dictionary<string, dynamic>
            {
                { "fileType", filteredDictionary},
                { "tabStatusName", tabStatusName },
                { "tabExamineName", tabExamineName },
                { "StatusName", StatusName },
                { "ApplyStatusName", ApplyStatusName }
            };
        }

        #endregion

        #region 案例库检索

        /// <summary>
        /// 检索列表
        /// </summary>
        /// <param name="pagedDto"></param>
        /// <returns></returns>
        [HttpGet("search")]
        public async Task<PagedDto<CaseDataDto>> QueryOnShelfCaseList([FromQuery] CaseListDto pagedDto)
        {
            pagedDto.Status = ECaseStatus.OnShelf;
            return (await _caseApplication.QueryAllCaseListAsync(pagedDto, HttpContext.RequestAborted)).ToPaged();
        }

        /// <summary>
        /// 检索列表前10
        /// </summary>
        /// <returns></returns>
        [HttpGet("search/top10")]
        public async Task<List<CasePageViewDto>> QueryTop10CaseList()
        {
            return await _caseListRepository.Queryable()
                .Take(10)
                .Where(x => x.Status == ECaseStatus.OnShelf)
                .Select(x => new CasePageViewDto
                {
                    Id = x.Id,
                    Title = x.Title,
                    PageView = x.PageView
                })
                .OrderBy(x => x.PageView, OrderByType.Desc)
                .ToListAsync();
        }

        #endregion
    }
}

