using Knot.Contracts.Conversations.Domain;
using Microsoft.EntityFrameworkCore;

namespace Knot.Modules.Conversations.Infrastructure.Persistence;

public sealed class ChatRepository : IChatRepository
{
    private readonly ChatsDbContext _dbContext;

    public ChatRepository(ChatsDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void Add(Chat chat)
    {
        _dbContext.Chats.Add(chat);
    }

    public void Update(Chat chat)
    {
        _dbContext.Chats.Update(chat);
    }

    public void Remove(Chat chat)
    {
        _dbContext.Chats.Remove(chat);
    }

    public async Task<Chat?> GetByIdAsync(Guid id, CancellationToken cancellationToken)
    {
        return await _dbContext.Chats
            .Include(c => c.Members)
            .FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
    }

    public async Task<Chat?> GetFavoritesAsync(Guid userId, CancellationToken cancellationToken)
    {
        return await _dbContext.Chats
            .Include(c => c.Members)
            .FirstOrDefaultAsync(c =>
                c.Type == ChatType.Favorites &&
                c.Members.Any(m => m.UserId == userId),
                cancellationToken);
    }

    public async Task<List<Chat>> GetUserChatsAsync(Guid userId, CancellationToken cancellationToken)
    {
        return await _dbContext.Chats
            .Include(c => c.Members)
            .Where(c => c.Members.Any(m => m.UserId == userId))
            .OrderByDescending(c => c.CreatedAt)
            .ToListAsync(cancellationToken);
    }
}

public sealed class FolderRepository : IFolderRepository
{
    private readonly ChatsDbContext _dbContext;

    public FolderRepository(ChatsDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void Add(Folder folder) => _dbContext.Folders.Add(folder);
    public void Update(Folder folder) => _dbContext.Folders.Update(folder);
    public void Remove(Folder folder) => _dbContext.Folders.Remove(folder);

    public async Task<Folder?> GetByIdAsync(Guid id, CancellationToken cancellationToken)
    {
        return await _dbContext.Folders.FirstOrDefaultAsync(f => f.Id == id, cancellationToken);
    }

    public async Task<List<Folder>> GetUserFoldersAsync(Guid userId, CancellationToken cancellationToken)
    {
        // В доменной модели Folder не имеет UserId напрямую (может быть общей сущностью), 
        // но по логике "папки в настройках пользователя" можно фильтровать через настройки.
        // Пока возвращаем все папки, которыми владеет пользователь (если добавить UserId) 
        // или все для упрощения первой итерации.
        return await _dbContext.Folders.ToListAsync(cancellationToken);
    }
}

public sealed class UserChatSettingsRepository : IUserChatSettingsRepository
{
    private readonly ChatsDbContext _dbContext;

    public UserChatSettingsRepository(ChatsDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void Add(UserChatSettings settings) => _dbContext.UserChatSettings.Add(settings);
    public void Update(UserChatSettings settings) => _dbContext.UserChatSettings.Update(settings);
    public void Remove(UserChatSettings settings) => _dbContext.UserChatSettings.Remove(settings);
    public void RemoveRange(IEnumerable<UserChatSettings> settings) => _dbContext.UserChatSettings.RemoveRange(settings);

    public async Task<UserChatSettings?> GetAsync(Guid userId, Guid chatId, CancellationToken cancellationToken)
    {
        return await _dbContext.UserChatSettings
            .FirstOrDefaultAsync(s => s.UserId == userId && s.ChatId == chatId, cancellationToken);
    }

    public async Task<List<UserChatSettings>> GetByUserIdAsync(Guid userId, CancellationToken cancellationToken)
    {
        return await _dbContext.UserChatSettings
            .Where(s => s.UserId == userId)
            .ToListAsync(cancellationToken);
    }
}

