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

namespace NexusIdentity.Api.Controllers;

[ApiController]
[Route("api/control-center")]
public sealed class ControlCenterController : ControllerBase
{
    private readonly IdentityDbContext _db;
    private readonly PolicyService _policyService;

    public ControlCenterController(IdentityDbContext db, PolicyService policyService)
    {
        _db = db;
        _policyService = policyService;
    }

    [HttpGet("dashboard")]
    public async Task<IActionResult> GetDashboard(CancellationToken ct)
    {
        var organizations = await _db.Organizations
            .AsNoTracking()
            .OrderBy(o => o.Name)
            .Select(o => new ControlCenterOrganizationSummary
            {
                Id = o.Id,
                Name = o.Name,
                IsActive = o.IsActive,
                UserCount = o.Users.Count(u => u.IsActive),
                DeviceCount = o.Devices.Count,
            })
            .ToListAsync(ct);

        var devices = await _db.Devices
            .AsNoTracking()
            .Include(d => d.Trust)
            .OrderByDescending(d => d.LastSeenUtc)
            .Take(100)
            .Select(d => new ControlCenterDeviceSummary
            {
                DeviceId = d.DeviceId,
                FriendlyName = d.FriendlyName,
                ComputerName = d.ComputerName,
                OrganizationId = d.OrganizationId,
                Owner = d.Owner,
                EnrollmentStatus = d.EnrollmentStatus,
                TrustStatus = d.Trust != null ? d.Trust.Status : "Unknown",
                LastSeenUtc = d.LastSeenUtc,
                Online = d.Online,
            })
            .ToListAsync(ct);

        var pendingEnrollments = await _db.EnrollmentRequests
            .AsNoTracking()
            .Where(e => e.Status == "Pending")
            .OrderByDescending(e => e.RequestedAtUtc)
            .Select(e => new ControlCenterPendingEnrollment
            {
                RequestId = e.Id.ToString(),
                DeviceId = e.DeviceId,
                OrganizationId = e.OrganizationId,
                UserName = e.UserName,
                DeviceFriendlyName = e.DeviceFriendlyName,
                RequestedAtUtc = e.RequestedAtUtc,
            })
            .ToListAsync(ct);

        var trustCounts = await _db.DeviceTrust
            .AsNoTracking()
            .GroupBy(t => t.Status)
            .Select(g => new { Status = g.Key, Count = g.Count() })
            .ToListAsync(ct);

        var trustSummary = new ControlCenterTrustSummary
        {
            Trusted = trustCounts.FirstOrDefault(t => t.Status == "Trusted")?.Count ?? 0,
            Pending = trustCounts.FirstOrDefault(t => t.Status == "Pending")?.Count ?? 0,
            Blocked = trustCounts.FirstOrDefault(t => t.Status == "Blocked")?.Count ?? 0,
            Unknown = trustCounts.FirstOrDefault(t => t.Status == "Unknown")?.Count ?? 0,
        };

        var policies = await _policyService.GetPoliciesAsync(organizationId: null, ct);

        return Ok(new ControlCenterDashboardResponse
        {
            GeneratedAtUtc = DateTime.UtcNow,
            OrganizationCount = organizations.Count,
            DeviceCount = await _db.Devices.CountAsync(ct),
            PendingEnrollmentCount = pendingEnrollments.Count,
            Organizations = organizations,
            Devices = devices,
            PendingEnrollments = pendingEnrollments,
            TrustSummary = trustSummary,
            Policies = policies.Select(p => new ControlCenterPolicySummary
            {
                Id = p.Id,
                Name = p.Name,
                Scope = p.Scope,
                IsEnabled = p.IsEnabled,
                Summary = p.Summary,
            }).ToList(),
        });
    }

    [HttpGet("policies")]
    public async Task<IActionResult> GetPolicies([FromQuery] string? organizationId, CancellationToken ct)
    {
        var policies = await _policyService.GetPoliciesAsync(organizationId, ct);
        return Ok(policies.Select(p => new ControlCenterPolicySummary
        {
            Id = p.Id,
            Name = p.Name,
            Scope = p.Scope,
            IsEnabled = p.IsEnabled,
            Summary = p.Summary,
        }));
    }
}

public sealed class ControlCenterDashboardResponse
{
    public DateTime GeneratedAtUtc { get; init; }
    public int OrganizationCount { get; init; }
    public int DeviceCount { get; init; }
    public int PendingEnrollmentCount { get; init; }
    public IReadOnlyList<ControlCenterOrganizationSummary> Organizations { get; init; } = [];
    public IReadOnlyList<ControlCenterDeviceSummary> Devices { get; init; } = [];
    public IReadOnlyList<ControlCenterPendingEnrollment> PendingEnrollments { get; init; } = [];
    public required ControlCenterTrustSummary TrustSummary { get; init; }
    public IReadOnlyList<ControlCenterPolicySummary> Policies { get; init; } = [];
}

public sealed class ControlCenterOrganizationSummary
{
    public required string Id { get; init; }
    public required string Name { get; init; }
    public bool IsActive { get; init; }
    public int UserCount { get; init; }
    public int DeviceCount { get; init; }
}

public sealed class ControlCenterDeviceSummary
{
    public required string DeviceId { get; init; }
    public required string FriendlyName { get; init; }
    public required string ComputerName { get; init; }
    public string? OrganizationId { get; init; }
    public required string Owner { get; init; }
    public required string EnrollmentStatus { get; init; }
    public required string TrustStatus { get; init; }
    public DateTime? LastSeenUtc { get; init; }
    public bool Online { get; init; }
}

public sealed class ControlCenterPendingEnrollment
{
    public required string RequestId { get; init; }
    public required string DeviceId { get; init; }
    public required string OrganizationId { get; init; }
    public required string UserName { get; init; }
    public required string DeviceFriendlyName { get; init; }
    public DateTime RequestedAtUtc { get; init; }
}

public sealed class ControlCenterTrustSummary
{
    public int Trusted { get; init; }
    public int Pending { get; init; }
    public int Blocked { get; init; }
    public int Unknown { get; init; }
}

public sealed class ControlCenterPolicySummary
{
    public required string Id { get; init; }
    public required string Name { get; init; }
    public required string Scope { get; init; }
    public bool IsEnabled { get; init; }
    public required string Summary { get; init; }
}
