using ColaFlow.Modules.Mcp.Domain.Entities;
using ColaFlow.Modules.Mcp.Domain.Repositories;
using ColaFlow.Modules.Mcp.Domain.ValueObjects;
using Microsoft.EntityFrameworkCore;

namespace ColaFlow.Modules.Mcp.Infrastructure.Persistence.Repositories;

/// <summary>
/// Repository implementation for TaskLock aggregate
/// </summary>
public sealed class TaskLockRepository : ITaskLockRepository
{
    private readonly McpDbContext _context;

    public TaskLockRepository(McpDbContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<TaskLock?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _context.TaskLocks
            .FirstOrDefaultAsync(t => t.Id == id, cancellationToken);
    }

    public async Task<IReadOnlyList<TaskLock>> GetByTenantAsync(
        Guid tenantId,
        CancellationToken cancellationToken = default)
    {
        return await _context.TaskLocks
            .Where(t => t.TenantId == tenantId)
            .OrderByDescending(t => t.AcquiredAt)
            .ToListAsync(cancellationToken);
    }

    public async Task<TaskLock?> GetActiveLockForResourceAsync(
        Guid tenantId,
        string resourceType,
        Guid resourceId,
        CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await _context.TaskLocks
            .FirstOrDefaultAsync(t => t.TenantId == tenantId
                && t.ResourceType == resourceType
                && t.ResourceId == resourceId
                && t.Status == TaskLockStatus.Active
                && t.ExpiresAt > now,
                cancellationToken);
    }

    public async Task<IReadOnlyList<TaskLock>> GetByLockHolderAsync(
        Guid tenantId,
        Guid lockHolderId,
        CancellationToken cancellationToken = default)
    {
        return await _context.TaskLocks
            .Where(t => t.TenantId == tenantId && t.LockHolderId == lockHolderId)
            .OrderByDescending(t => t.AcquiredAt)
            .ToListAsync(cancellationToken);
    }

    public async Task<IReadOnlyList<TaskLock>> GetByStatusAsync(
        Guid tenantId,
        TaskLockStatus status,
        CancellationToken cancellationToken = default)
    {
        return await _context.TaskLocks
            .Where(t => t.TenantId == tenantId && t.Status == status)
            .OrderByDescending(t => t.AcquiredAt)
            .ToListAsync(cancellationToken);
    }

    public async Task<IReadOnlyList<TaskLock>> GetExpiredAsync(
        CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await _context.TaskLocks
            .Where(t => t.Status == TaskLockStatus.Active && t.ExpiresAt < now)
            .ToListAsync(cancellationToken);
    }

    public async Task<bool> IsResourceLockedAsync(
        Guid tenantId,
        string resourceType,
        Guid resourceId,
        CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await _context.TaskLocks
            .AnyAsync(t => t.TenantId == tenantId
                && t.ResourceType == resourceType
                && t.ResourceId == resourceId
                && t.Status == TaskLockStatus.Active
                && t.ExpiresAt > now,
                cancellationToken);
    }

    public async Task<bool> IsResourceLockedByAsync(
        Guid tenantId,
        string resourceType,
        Guid resourceId,
        Guid lockHolderId,
        CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await _context.TaskLocks
            .AnyAsync(t => t.TenantId == tenantId
                && t.ResourceType == resourceType
                && t.ResourceId == resourceId
                && t.LockHolderId == lockHolderId
                && t.Status == TaskLockStatus.Active
                && t.ExpiresAt > now,
                cancellationToken);
    }

    public async Task AddAsync(TaskLock taskLock, CancellationToken cancellationToken = default)
    {
        await _context.TaskLocks.AddAsync(taskLock, cancellationToken);
    }

    public Task UpdateAsync(TaskLock taskLock, CancellationToken cancellationToken = default)
    {
        _context.TaskLocks.Update(taskLock);
        return Task.CompletedTask;
    }

    public Task DeleteAsync(TaskLock taskLock, CancellationToken cancellationToken = default)
    {
        _context.TaskLocks.Remove(taskLock);
        return Task.CompletedTask;
    }

    public async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        return await _context.SaveChangesAsync(cancellationToken);
    }
}
