using Knot.Modules.Stories.Application.Stories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Knot.Shared.Kernel;
using Knot.Modules.Stories.Domain;

using Microsoft.EntityFrameworkCore;





using Knot.Modules.Stories.Application.DTOs;
using Knot.Modules.Stories.Infrastructure.Database;

namespace Knot.Modules.Stories.Application.Stories.Queries.GetStoryViewers;

public record GetStoryViewersQuery(Guid UserId, Guid StoryId) : IQuery<List<StoryViewerDto>>;

internal sealed class GetStoryViewersQueryHandler : IQueryHandler<GetStoryViewersQuery, List<StoryViewerDto>>
{
    private readonly StoriesDbContext _context;
    private readonly Knot.Modules.Stories.Application.Abstractions.IStoryRepository _storyRepository;
    private readonly IUserRepository _userRepository;

    public GetStoryViewersQueryHandler(StoriesDbContext context, Knot.Modules.Stories.Application.Abstractions.IStoryRepository storyRepository, IUserRepository userRepository)
    {
        _context = context;
        _storyRepository = storyRepository;
        _userRepository = userRepository;
    }

    public async Task<Result<List<StoryViewerDto>>> Handle(GetStoryViewersQuery request, CancellationToken cancellationToken)
    {
        var story = await _storyRepository.GetByIdAsync(request.StoryId, cancellationToken);

        if (story == null)
        {
            return Result.Failure<List<StoryViewerDto>>(StoryErrors.StoryNotFound);
        }
        if (story.UserId != request.UserId)
        {
            return Result.Failure<List<StoryViewerDto>>(StoryErrors.Unauthorized);
        }

        var viewersRecords = await _context.StoryViewers
            .Where(v => v.StoryId == request.StoryId)
            .OrderByDescending(v => v.ViewedAt)
            .ToListAsync(cancellationToken);

        var viewers = new List<StoryViewerDto>();

        foreach (var viewerRecord in viewersRecords)
        {
            var user = await _userRepository.GetByIdAsync(viewerRecord.UserId, cancellationToken);
            if (user == null)
            {
                continue;
            }

            viewers.Add(new StoryViewerDto(
                user.Id,
                user.Username,
                user.DisplayName,
                user.Avatar,
                viewerRecord.ViewedAt
            ));
        }

        return Result.Success(viewers);
    }
}



