using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NexusIdentity.Api.Data;
using NexusIdentity.Api.Models;

namespace NexusIdentity.Api.Controllers;

[ApiController]
[Route("api/registry/users")]
public sealed class RegistryUsersController : ControllerBase
{
    private readonly IdentityDbContext _db;

    public RegistryUsersController(IdentityDbContext db)
    {
        _db = db;
    }

    [HttpGet]
    public async Task<IActionResult> List([FromQuery] string? organizationId, CancellationToken ct)
    {
        var query = _db.Users.AsNoTracking().AsQueryable();

        if (!string.IsNullOrWhiteSpace(organizationId))
        {
            query = query.Where(u => u.OrganizationId == organizationId);
        }

        var users = await query
            .OrderBy(u => u.DisplayName)
            .Select(u => new RegistryUserDto
            {
                Id = u.Id.ToString(),
                Email = u.Email,
                DisplayName = u.DisplayName,
                Role = u.Role,
                OrganizationId = u.OrganizationId,
                IsActive = u.IsActive,
                CreatedAt = u.CreatedAt,
            })
            .ToListAsync(ct);

        return Ok(users);
    }

    [HttpGet("{id:guid}")]
    public async Task<IActionResult> Get(Guid id, CancellationToken ct)
    {
        var user = await _db.Users
            .AsNoTracking()
            .Where(u => u.Id == id)
            .Select(u => new RegistryUserDto
            {
                Id = u.Id.ToString(),
                Email = u.Email,
                DisplayName = u.DisplayName,
                Role = u.Role,
                OrganizationId = u.OrganizationId,
                IsActive = u.IsActive,
                CreatedAt = u.CreatedAt,
            })
            .FirstOrDefaultAsync(ct);

        return user is null ? NotFound() : Ok(user);
    }

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] CreateRegistryUserRequest request, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(request.DisplayName))
        {
            return BadRequest(new { error = "DisplayName is required." });
        }

        if (!string.IsNullOrWhiteSpace(request.OrganizationId))
        {
            var orgExists = await _db.Organizations.AnyAsync(o => o.Id == request.OrganizationId, ct);
            if (!orgExists)
            {
                return BadRequest(new { error = "Organization not found." });
            }
        }

        var user = new UserEntity
        {
            Id = Guid.NewGuid(),
            Email = request.Email?.Trim() ?? $"{Guid.NewGuid():N}@registry.local",
            DisplayName = request.DisplayName.Trim(),
            Role = string.IsNullOrWhiteSpace(request.Role) ? "User" : request.Role.Trim(),
            OrganizationId = request.OrganizationId,
            PasswordHash = string.Empty,
            IsActive = true,
            CreatedAt = DateTime.UtcNow,
        };

        _db.Users.Add(user);
        await _db.SaveChangesAsync(ct);

        return CreatedAtAction(nameof(Get), new { id = user.Id }, new RegistryUserDto
        {
            Id = user.Id.ToString(),
            Email = user.Email,
            DisplayName = user.DisplayName,
            Role = user.Role,
            OrganizationId = user.OrganizationId,
            IsActive = user.IsActive,
            CreatedAt = user.CreatedAt,
        });
    }
}

public sealed class RegistryUserDto
{
    public required string Id { get; init; }
    public required string Email { get; init; }
    public required string DisplayName { get; init; }
    public required string Role { get; init; }
    public string? OrganizationId { get; init; }
    public bool IsActive { get; init; }
    public DateTime CreatedAt { get; init; }
}

public sealed class CreateRegistryUserRequest
{
    public required string DisplayName { get; init; }
    public string? Email { get; init; }
    public string? Role { get; init; }
    public string? OrganizationId { get; init; }
}
