using Furion.DatabaseAccessor.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using YBEE.EQM.Core;

namespace YBEE.EQM.Application;

/// <summary>
/// 监测机构反馈结果管理服务
/// </summary>
public class ExamOrgResultService : IExamOrgResultService, ITransient
{
    private readonly IRepository<ExamOrgResult> _rep;
    private readonly EqmSiteOptions _eqmSiteOptions;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public ExamOrgResultService(IRepository<ExamOrgResult> rep, IOptions<EqmSiteOptions> options, IHttpContextAccessor httpContextAccessor)
    {
        _rep = rep;
        _eqmSiteOptions = options.Value;
        _httpContextAccessor = httpContextAccessor;
    }

    /// <summary>
    /// 添加结果文件
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task Add(AddExamOrgResultInput input)
    {
        var item = input.Adapt<ExamOrgResult>();
        await item.InsertNowAsync();
    }

    /// <summary>
    /// 删除文件
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task Del(BaseId input)
    {
        var item = await _rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
        var fpath = Path.Combine(_eqmSiteOptions.ExamResultRoot, item.FilePath);
        if (File.Exists(fpath))
        {
            File.Delete(fpath);
        }
        await item.DeleteAsync();
    }

    /// <summary>
    /// 保存下载记录
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task SaveDownloadRecord(int id)
    {
        var httpContext = _httpContextAccessor.HttpContext;

        ExamOrgResultDownload item = new()
        {
            ExamOrgResultId = id,
            SysUserId = CurrentSysUserInfo.SysUserId,
            Account = CurrentSysUserInfo.Account,
            Ip = httpContext.GetRequestIPv4(),
            DownloadTime = DateTime.Now,
        };

        await _rep.Change<ExamOrgResultDownload>().InsertNowAsync(item);
    }

    /// <summary>
    /// 获取ID获取监测机构反馈文件信息
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<ExamOrgResultOutput> GetById(int id)
    {
        var item = await _rep.DetachedEntities.FirstOrDefaultAsync(t => t.Id == id) ?? throw Oops.Oh(ErrorCode.E2001);
        return item.Adapt<ExamOrgResultOutput>();
    }

    /// <summary>
    /// 根据监测计划获取机构反馈文件列表
    /// </summary>
    /// <param name="examPlanId"></param>
    /// <returns></returns>
    public async Task<List<ExamDataPublishOrgResultOutput>> GetByExamPlanId(int examPlanId)
    {
        var pubItems = await _rep.Change<ExamDataPublish>().DetachedEntities.Where(t => t.ExamPlanId == examPlanId && t.Status == PublishStatus.PUBLISHED).ProjectToType<ExamDataPublishOrgResultOutput>().ToListAsync();
        foreach (var pubItem in pubItems)
        {
            if (pubItem.Status == PublishStatus.PUBLISHED)
            {
                var items = await _rep.DetachedEntities.Where(t => t.SysOrgId == CurrentSysUserInfo.SysOrgId && t.ExamPlanId == examPlanId && t.ExamDataPublishId == pubItem.Id).ProjectToType<ExamOrgResultOutput>().ToListAsync();
                pubItem.ExamOrgResultList = items;
            }
        }

        return pubItems;
    }

    /// <summary>
    /// 根据发布内容ID获取机构文件列表
    /// </summary>
    /// <param name="publishId"></param>
    /// <returns></returns>
    public async Task<List<ExamOrgResultOutput>> GetByPublishId(int publishId)
    {
        var pub = await _rep.Change<ExamDataPublish>().FirstOrDefaultAsync(t => t.Id == publishId) ?? throw Oops.Oh(ErrorCode.E2001);
        var items = await _rep.DetachedEntities.Where(t => t.ExamDataPublishId == publishId).ProjectToType<ExamOrgResultOutput>().OrderBy(t => t.SysOrgId).ToListAsync();

        var norgs = await (from o in _rep.Change<ExamOrg>().AsQueryable()
                           where o.ExamPlanId == pub.ExamPlanId && !(from r in items select r.ExamOrgId).Contains(o.Id)
                           select o).ProjectToType<ExamOrgOutput>().ToListAsync();

        int maxId = 1;
        if (items.Any())
        {
            maxId = items.Max(t => t.Id) + 1;
        }
        items.AddRange(norgs.Select(t => new ExamOrgResultOutput()
        {
            Id = maxId++,
            ExamDataPublishId = publishId,
            ExamOrgId = t.Id,
            ExamOrg = t,
        }));
        return items;
    }
}
