using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;

namespace Fengling.Platform.Infrastructure;

/// <summary>
/// 路由存储实现
/// </summary>
public class RouteStore<TContext> : IRouteStore
    where TContext : PlatformDbContext
{
    private readonly TContext _context;
    private readonly DbSet<GwTenantRoute> _routes;

    public RouteStore(TContext context)
    {
        _context = context;
        _routes = context.GwTenantRoutes;
    }

    public void Dispose() { }

    public virtual Task<GwTenantRoute?> FindByIdAsync(long? id, CancellationToken cancellationToken = default)
    {
        if (id == null) return Task.FromResult<GwTenantRoute?>(null);
        return _routes.FirstOrDefaultAsync(r => r.Id == id, cancellationToken);
    }

    public virtual Task<GwTenantRoute?> FindByTenantCodeAsync(string tenantCode, CancellationToken cancellationToken = default)
    {
        return _routes.FirstOrDefaultAsync(r => r.TenantCode == tenantCode && !r.IsDeleted, cancellationToken);
    }

    public virtual Task<GwTenantRoute?> FindByClusterIdAsync(string clusterId, CancellationToken cancellationToken = default)
    {
        return _routes.FirstOrDefaultAsync(r => r.ClusterId == clusterId && !r.IsDeleted, cancellationToken);
    }

    public virtual async Task<IList<GwTenantRoute>> GetAllAsync(CancellationToken cancellationToken = default)
    {
        return await _routes.Where(r => !r.IsDeleted).ToListAsync(cancellationToken);
    }

    public virtual async Task<IList<GwTenantRoute>> GetPagedAsync(int page, int pageSize, string? tenantCode = null,
        string? serviceName = null, RouteStatus? status = null, CancellationToken cancellationToken = default)
    {
        var query = _routes.AsQueryable();

        if (!string.IsNullOrEmpty(tenantCode))
            query = query.Where(r => r.TenantCode.Contains(tenantCode));

        if (!string.IsNullOrEmpty(serviceName))
            query = query.Where(r => r.ServiceName.Contains(serviceName));

        if (status.HasValue)
            query = query.Where(r => r.Status == (int)status.Value);

        return await query
            .Where(r => !r.IsDeleted)
            .OrderByDescending(r => r.CreatedTime)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync(cancellationToken);
    }

    public virtual async Task<int> GetCountAsync(string? tenantCode = null, string? serviceName = null,
        RouteStatus? status = null, CancellationToken cancellationToken = default)
    {
        var query = _routes.AsQueryable();

        if (!string.IsNullOrEmpty(tenantCode))
            query = query.Where(r => r.TenantCode.Contains(tenantCode));

        if (!string.IsNullOrEmpty(serviceName))
            query = query.Where(r => r.ServiceName.Contains(serviceName));

        if (status.HasValue)
            query = query.Where(r => r.Status == (int)status.Value);

        return await query.Where(r => !r.IsDeleted).CountAsync(cancellationToken);
    }

    public virtual async Task<IdentityResult> CreateAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
    {
        _routes.Add(route);
        await _context.SaveChangesAsync(cancellationToken);
        return IdentityResult.Success;
    }

    public virtual async Task<IdentityResult> UpdateAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
    {
        route.UpdatedTime = DateTime.UtcNow;
        _routes.Update(route);
        await _context.SaveChangesAsync(cancellationToken);
        return IdentityResult.Success;
    }

    public virtual async Task<IdentityResult> DeleteAsync(GwTenantRoute route, CancellationToken cancellationToken = default)
    {
        // 软删除
        route.IsDeleted = true;
        route.UpdatedTime = DateTime.UtcNow;
        _routes.Update(route);
        await _context.SaveChangesAsync(cancellationToken);
        return IdentityResult.Success;
    }
}
