using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Knot.Modules.Stories.Application.Abstractions;
using Knot.Modules.Stories.Domain;
using MongoDB.Driver;

namespace Knot.Modules.Stories.Infrastructure.Persistence.Mongo;

internal sealed class StoryRepository : IStoryRepository
{
    private readonly IMongoCollection<Story> _stories;

    public StoryRepository(IMongoDatabase database)
    {
        _stories = database.GetCollection<Story>("stories");
    }

    public async Task AddAsync(Story story, CancellationToken cancellationToken = default)
    {
        await _stories.InsertOneAsync(story, new InsertOneOptions(), cancellationToken);
    }

    public async Task UpdateAsync(Story story, CancellationToken cancellationToken = default)
    {
        await _stories.ReplaceOneAsync(s => s.Id == story.Id, story, new ReplaceOptions(), cancellationToken);
    }

    public async Task DeleteAsync(Story story, CancellationToken cancellationToken = default)
    {
        await _stories.DeleteOneAsync(s => s.Id == story.Id, cancellationToken);
    }

    public async Task<Story?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
    {
        return await _stories.Find(s => s.Id == id).FirstOrDefaultAsync(cancellationToken);
    }

    public async Task<List<Story>> GetActiveUserStoriesAsync(Guid userId, CancellationToken cancellationToken = default)
    {
        var yesterday = DateTime.UtcNow.AddHours(-24);
        return await _stories.Find(s => s.UserId == userId && s.CreatedAt > yesterday)
                             .SortByDescending(s => s.CreatedAt)
                             .ToListAsync(cancellationToken);
    }

    public async Task<List<Story>> GetFeedStoriesAsync(List<Guid> userIds, CancellationToken cancellationToken = default)
    {
        var yesterday = DateTime.UtcNow.AddHours(-24);
        return await _stories.Find(s => s.CreatedAt > yesterday && userIds.Contains(s.UserId))
                             .SortByDescending(s => s.CreatedAt)
                             .Limit(100)
                             .ToListAsync(cancellationToken);
    }

    public async Task IncrementViewsCountAsync(Guid storyId, CancellationToken cancellationToken = default)
    {
        var update = Builders<Story>.Update.Inc(s => s.ViewsCount, 1);
        await _stories.UpdateOneAsync(s => s.Id == storyId, update, new UpdateOptions(), cancellationToken);
    }
}
