using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Knot.Contracts.Admin.Abstractions;
using Knot.Contracts.Auth.Domain;
using Knot.Contracts.Conversations.Abstractions;
using Knot.Contracts.Messaging.Application.Abstractions;
using Knot.Modules.Admin.Application.Admin.DTOs;
using MediatR;

namespace Knot.Modules.Admin.Application.Admin.Queries;

public record SearchUsersQuery(string Query) : IQuery<List<AdminUserDto>>;

internal sealed class SearchUsersQueryHandler : IQueryHandler<SearchUsersQuery, List<AdminUserDto>>
{
    private readonly IUserRepository _userRepository;
    private readonly Knot.Contracts.Messaging.Application.Abstractions.IUserStatsService _statsService;
    private readonly IUserStatusService _statusService;

    public SearchUsersQueryHandler(
        IUserRepository userRepository,
        Knot.Contracts.Messaging.Application.Abstractions.IUserStatsService statsService,
        IUserStatusService statusService)
    {
        _userRepository = userRepository;
        _statsService = statsService;
        _statusService = statusService;
    }

    public async Task<Result<List<AdminUserDto>>> Handle(SearchUsersQuery request, CancellationToken ct)
    {
        try
        {
            var users = await _userRepository.SearchUsersAsync(request.Query ?? "", ct);
            if (!users.Any()) return Result.Success(new List<AdminUserDto>());

            var userIds = users.Select(u => u.Id).ToList();

            var statsMap = await _statsService.GetStatsForUsersAsync(userIds, ct);

            var result = users.Select(u =>
            {
                var stats = statsMap.GetValueOrDefault(u.Id, new Knot.Contracts.Messaging.Application.Abstractions.UserStats(0, 0L));
                var isOnline = _statusService.IsUserOnline(u.Id.ToString());


                return new AdminUserDto(
                    u.Id,
                    u.Username ?? "unknown",
                    u.DisplayName ?? "User",
                    u.Email,
                    u.Avatar,
                    u.CreatedAt,
                    isOnline,
                    isOnline ? DateTime.UtcNow : (u.CreatedAt),
                    u.IsBanned,
                    stats.MessageCount,
                    stats.StorageSize
                );
            }).ToList();

            return Result.Success(result);
        }
        catch (Exception ex)
        {
            return Result.Failure<List<AdminUserDto>>(new Error("Admin.SearchUsers.Error", $"Error searching users: {ex.Message}"));
        }
    }
}
