using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using SqlSugar;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Yi.Framework.AiHub.Application.Contracts.Dtos.Announcement;
using Yi.Framework.AiHub.Application.Contracts.IServices;
using Yi.Framework.AiHub.Domain.Entities;
using Yi.Framework.SqlSugarCore.Abstractions;

namespace Yi.Framework.AiHub.Application.Services;

/// <summary>
/// 公告服务
/// </summary>
public class AnnouncementService : ApplicationService, IAnnouncementService
{
    private readonly ISqlSugarRepository<AnnouncementAggregateRoot> _announcementRepository;
    private readonly IConfiguration _configuration;
    private readonly IDistributedCache<AnnouncementCacheDto> _announcementCache;
    private const string AnnouncementCacheKey = "AiHub:Announcement";

    public AnnouncementService(
        ISqlSugarRepository<AnnouncementAggregateRoot> announcementRepository,
        IConfiguration configuration,
        IDistributedCache<AnnouncementCacheDto> announcementCache)
    {
        _announcementRepository = announcementRepository;
        _configuration = configuration;
        _announcementCache = announcementCache;
    }

    /// <summary>
    /// 获取公告信息（前端首页使用，允许匿名访问）
    /// </summary>
    [AllowAnonymous]
    public async Task<List<AnnouncementLogDto>> GetAsync()
    {
        // 使用 GetOrAddAsync 从缓存获取或添加数据，缓存1小时
        var cacheData = await _announcementCache.GetOrAddAsync(
            AnnouncementCacheKey,
            async () => await LoadAnnouncementDataAsync(),
            () => new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
            }
        );

        return cacheData?.Logs ?? new List<AnnouncementLogDto>();
    }

    /// <summary>
    /// 获取公告列表（后台管理使用）
    /// </summary>
    [Authorize(Roles = "admin")]
    [HttpGet("announcement/list")]
    public async Task<PagedResultDto<AnnouncementDto>> GetListAsync(AnnouncementGetListInput input)
    {
        var query = _announcementRepository._DbQueryable
            .WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey),
                x => x.Title.Contains(input.SearchKey!) || (x.Remark != null && x.Remark.Contains(input.SearchKey!)))
            .WhereIF(input.Type.HasValue, x => x.Type == input.Type!.Value)
            .OrderByDescending(x => x.StartTime);

        var totalCount = await query.CountAsync();
        var items = await query
            .Skip(input.SkipCount)
            .Take(input.MaxResultCount)
            .ToListAsync();

        return new PagedResultDto<AnnouncementDto>(
            totalCount,
            items.Adapt<List<AnnouncementDto>>()
        );
    }

    /// <summary>
    /// 根据ID获取公告
    /// </summary>
    [Authorize(Roles = "admin")]
    [HttpGet("{id}")]
    public async Task<AnnouncementDto> GetByIdAsync(Guid id)
    {
        var entity = await _announcementRepository.GetByIdAsync(id);
        if (entity == null)
        {
            throw new Exception("公告不存在");
        }
        return entity.Adapt<AnnouncementDto>();
    }

    /// <summary>
    /// 创建公告
    /// </summary>
    [Authorize(Roles = "admin")]
    [HttpPost]
    public async Task<AnnouncementDto> CreateAsync(AnnouncementCreateInput input)
    {
        var entity = input.Adapt<AnnouncementAggregateRoot>();
        await _announcementRepository.InsertAsync(entity);

        // 清除缓存
        await _announcementCache.RemoveAsync(AnnouncementCacheKey);

        return entity.Adapt<AnnouncementDto>();
    }

    /// <summary>
    /// 更新公告
    /// </summary>
    [Authorize(Roles = "admin")]
    [HttpPut]
    public async Task<AnnouncementDto> UpdateAsync(AnnouncementUpdateInput input)
    {
        var entity = await _announcementRepository.GetByIdAsync(input.Id);
        if (entity == null)
        {
            throw new Exception("公告不存在");
        }

        // 更新字段
        entity.Title = input.Title;
        entity.Content = input.Content;
        entity.Remark = input.Remark;
        entity.ImageUrl = input.ImageUrl;
        entity.StartTime = input.StartTime;
        entity.EndTime = input.EndTime;
        entity.Type = input.Type;
        entity.Url = input.Url;

        await _announcementRepository.UpdateAsync(entity);

        // 清除缓存
        await _announcementCache.RemoveAsync(AnnouncementCacheKey);

        return entity.Adapt<AnnouncementDto>();
    }

    /// <summary>
    /// 删除公告
    /// </summary>
    [Authorize(Roles = "admin")]
    [HttpDelete("announcement/{id}")]
    public async Task DeleteAsync(Guid id)
    {
        var entity = await _announcementRepository.GetByIdAsync(id);
        if (entity == null)
        {
            throw new Exception("公告不存在");
        }

        await _announcementRepository.DeleteAsync(entity);

        // 清除缓存
        await _announcementCache.RemoveAsync(AnnouncementCacheKey);
    }

    /// <summary>
    /// 从数据库加载公告数据
    /// </summary>
    private async Task<AnnouncementCacheDto> LoadAnnouncementDataAsync()
    {
        // 一次性查出全部公告（不排序）
        var logs = await _announcementRepository._DbQueryable
            .ToListAsync();

        var now = DateTime.Now;

        // 内存中处理排序
        var orderedLogs = logs
            .OrderByDescending(x =>
                x.StartTime <= now &&
                (x.EndTime == null || x.EndTime >= now)
            )
            .ThenByDescending(x => x.StartTime)
            .ToList();

        // 转换为 DTO
        var logDtos = orderedLogs.Adapt<List<AnnouncementLogDto>>();
        return new AnnouncementCacheDto
        {
            Logs = logDtos
        };
    }
}
