using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Knot.Modules.Stories.Application.Abstractions;
using Knot.Modules.Stories.Application.DTOs;
using Knot.Modules.Stories.Infrastructure.Database;
using Knot.Shared.Kernel;
using MediatR;
using Microsoft.EntityFrameworkCore;



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

public record GetUserStoriesQuery(Guid CurrentUserId, Guid TargetUserId) : IQuery<StoryGroupDto>;

internal sealed class GetUserStoriesQueryHandler : IQueryHandler<GetUserStoriesQuery, StoryGroupDto>
{
    private readonly StoriesDbContext _context;
    private readonly IStoryRepository _storyRepository;
    private readonly IUserRepository _userRepository;

    public GetUserStoriesQueryHandler(StoriesDbContext context, IStoryRepository storyRepository, IUserRepository userRepository)
    {
        _context = context;
        _storyRepository = storyRepository;
        _userRepository = userRepository;
    }

    public async Task<Result<StoryGroupDto>> Handle(GetUserStoriesQuery request, CancellationToken cancellationToken)
    {
        var user = await _userRepository.GetByIdAsync(request.TargetUserId, cancellationToken);
        if (user == null)
            return Result.Failure<StoryGroupDto>(Knot.Modules.Stories.Domain.IdentityErrors.UserNotFound);

        // Если пользователь внешний — идем в федерацию
        if (user.IsExternal && !string.IsNullOrEmpty(user.Domain))
        {
            return await GetFederatedStories(user, request.CurrentUserId, cancellationToken);
        }

        var stories = await _storyRepository.GetActiveUserStoriesAsync(request.TargetUserId, cancellationToken);
        var storyIds = stories.Select(s => s.Id).ToList();

        var viewedStoriesIds = await _context.StoryViewers
            .Where(v => v.UserId == request.CurrentUserId && storyIds.Contains(v.StoryId))
            .Select(v => v.StoryId)
            .ToListAsync(cancellationToken);

        var result = new StoryGroupDto(
            new StoryUserDto(user.Id, user.Username, user.DisplayName, user.Avatar),
            stories.Select(s => new StoryDto(
                s.Id,
                s.Type,
                s.MediaUrl,
                s.Content,
                s.BgColor,
                s.IsMuted,
                s.CreatedAt,
                s.ViewsCount,
                viewedStoriesIds.Contains(s.Id)
            )).ToList(),
            stories.Any(s => !viewedStoriesIds.Contains(s.Id))
        );

        return Result.Success(result);
    }

    private async Task<Result<StoryGroupDto>> GetFederatedStories(Knot.Contracts.Relations.Domain.UserReplica user, Guid currentUserId, CancellationToken ct)
    {
        // В будущем: Реальный вызов через HttpClient к удаленному домену
        // return await _federationGateway.FetchStoriesAsync(user.Domain, user.Id);
        return Result.Failure<StoryGroupDto>(new Error("Federation.StoriesNotImplemented", "Stories from this domain are temporarily unavailable."));
    }
}


