using FastEndpoints;
using SpaceGame.Api.Auth.Runtime;
using SpaceGame.Api.Auth.Simulation;
using SpaceGame.Api.PlayerFaction.Simulation;

namespace SpaceGame.Api.PlayerFaction.Api;

public sealed class GetPlayerIdentitiesHandler(IAuthRepository authRepository, IPlayerStateStore playerStateStore)
  : EndpointWithoutRequest<IReadOnlyList<PlayerIdentitySummaryResponse>>
{
    public override void Configure()
    {
        Get("/api/player-faction/identities");
        Policies(AuthPolicyNames.GmAccess);
    }

    public override async Task HandleAsync(CancellationToken cancellationToken)
    {
        var users = await authRepository.ListUsersAsync(cancellationToken);
        var playerFactionsById = playerStateStore.GetPlayerFactions()
          .ToDictionary(player => player.Id, StringComparer.Ordinal);

        var responses = new List<PlayerIdentitySummaryResponse>(users.Count + playerFactionsById.Count);
        var seenIds = new HashSet<string>(StringComparer.Ordinal);

        foreach (var user in users)
        {
            var userId = user.Id.ToString("N");
            playerFactionsById.TryGetValue(userId, out var playerFaction);
            responses.Add(new PlayerIdentitySummaryResponse(
              userId,
              user.Email,
              user.Roles,
              playerFaction is not null,
              playerFaction?.Id,
              playerFaction?.Label,
              playerFaction?.SovereignFactionId));
            seenIds.Add(userId);
        }

        foreach (var playerFaction in playerStateStore.GetPlayerFactions())
        {
            if (!seenIds.Add(playerFaction.Id))
            {
                continue;
            }

            responses.Add(new PlayerIdentitySummaryResponse(
              playerFaction.Id,
              $"{playerFaction.Id}@unknown",
              Array.Empty<string>(),
              true,
              playerFaction.Id,
              playerFaction.Label,
              playerFaction.SovereignFactionId));
        }

        await SendOkAsync(
          responses
            .OrderBy(response => response.Email, StringComparer.OrdinalIgnoreCase)
            .ThenBy(response => response.UserId, StringComparer.Ordinal)
            .ToList(),
          cancellationToken);
    }
}

public sealed record PlayerIdentitySummaryResponse(
  string UserId,
  string Email,
  IReadOnlyList<string> Roles,
  bool HasPlayerFaction,
  string? PlayerFactionId,
  string? PlayerFactionLabel,
  string? SovereignFactionId);
