using foodmarket.Application.Common;
using foodmarket.Domain.Organizations;
using foodmarket.Infrastructure.Persistence;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;

namespace foodmarket.Api.Controllers.SuperAdmin;

/// <summary>SuperAdmin: setup-status, dashboard статистика, audit log.</summary>
[ApiController]
[Authorize(Roles = "SuperAdmin")]
[Route("api/super-admin")]
public class SuperAdminController : ControllerBase
{
    private readonly AppDbContext _db;

    public SuperAdminController(AppDbContext db) => _db = db;

    public record SetupStatusDto(bool NeedsSetup, int OrgCount);

    [HttpGet("setup-status")]
    public async Task<ActionResult<SetupStatusDto>> GetSetupStatus(CancellationToken ct)
    {
        var count = await _db.Organizations.IgnoreQueryFilters().CountAsync(ct);
        return new SetupStatusDto(NeedsSetup: count == 0, OrgCount: count);
    }

    public record DashboardStats(
        int TotalOrgs, int ActiveOrgs, int ArchivedOrgs,
        int TotalUsers, int ActiveUsers,
        int RegistrationsLast30Days);

    [HttpGet("dashboard")]
    public async Task<ActionResult<DashboardStats>> Dashboard(CancellationToken ct)
    {
        // Метрики SuperAdmin'а — кабинет SaaS-владельца, не операционные
        // показатели магазинов. Биллинговые KPI (MRR, должники, платящие)
        // считаем на UI как заглушки — отдельный модуль подписки в Phase 4+.
        var monthAgo = DateTime.UtcNow.AddDays(-30);
        return new DashboardStats(
            TotalOrgs: await _db.Organizations.IgnoreQueryFilters().CountAsync(ct),
            ActiveOrgs: await _db.Organizations.IgnoreQueryFilters().CountAsync(o => !o.IsArchived, ct),
            ArchivedOrgs: await _db.Organizations.IgnoreQueryFilters().CountAsync(o => o.IsArchived, ct),
            TotalUsers: await _db.Users.CountAsync(ct),
            ActiveUsers: await _db.Users.CountAsync(u => u.IsActive, ct),
            RegistrationsLast30Days: await _db.Organizations.IgnoreQueryFilters().CountAsync(o => o.CreatedAt >= monthAgo, ct));
    }

    public record SystemSettingsDto(int ArchiveRetentionDays);
    public record SystemSettingsInput(int ArchiveRetentionDays);

    [HttpGet("settings")]
    public async Task<ActionResult<SystemSettingsDto>> GetSettings(CancellationToken ct)
    {
        var s = await _db.SystemSettings.FirstOrDefaultAsync(ct);
        return new SystemSettingsDto(s?.ArchiveRetentionDays ?? 30);
    }

    [HttpPut("settings")]
    public async Task<ActionResult<SystemSettingsDto>> UpdateSettings([FromBody] SystemSettingsInput input, CancellationToken ct)
    {
        if (input.ArchiveRetentionDays < 0 || input.ArchiveRetentionDays > 3650)
            return BadRequest(new { error = "ArchiveRetentionDays должен быть в диапазоне 0–3650." });
        var s = await _db.SystemSettings.FirstOrDefaultAsync(ct);
        var prev = s?.ArchiveRetentionDays;
        if (s is null)
        {
            s = new SystemSettings { ArchiveRetentionDays = input.ArchiveRetentionDays };
            _db.SystemSettings.Add(s);
        }
        else
        {
            s.ArchiveRetentionDays = input.ArchiveRetentionDays;
        }
        await _db.SaveChangesAsync(ct);

        // Audit-log смены настройки
        var userIdRaw = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub");
        Guid.TryParse(userIdRaw, out var uid);
        _db.SuperAdminAuditLogs.Add(new SuperAdminAuditLog
        {
            SuperAdminUserId = uid,
            ActionType = "EditSystemSettings",
            Description = $"ArchiveRetentionDays: {prev?.ToString() ?? "(default 30)"} → {input.ArchiveRetentionDays}",
            ChangesJson = $"{{\"archiveRetentionDays\":{{\"from\":{prev?.ToString() ?? "30"},\"to\":{input.ArchiveRetentionDays}}}}}",
            IpAddress = HttpContext?.Connection?.RemoteIpAddress?.ToString() ?? "",
        });
        await _db.SaveChangesAsync(ct);
        return new SystemSettingsDto(s.ArchiveRetentionDays);
    }

    public record AuditRow(
        Guid Id, DateTime CreatedAt, Guid SuperAdminUserId,
        string ActionType, Guid? OrganizationId, string? OrganizationName,
        string? EntityType, Guid? EntityId, string? Description, string? Reason, string IpAddress);

    [HttpGet("audit-log")]
    public async Task<ActionResult<PagedResult<AuditRow>>> AuditLog(
        [FromQuery] PagedRequest req,
        [FromQuery] Guid? organizationId,
        [FromQuery] string? actionType,
        [FromQuery] DateTime? from,
        [FromQuery] DateTime? to,
        CancellationToken ct)
    {
        var q = _db.SuperAdminAuditLogs.AsNoTracking().AsQueryable();
        if (organizationId is not null) q = q.Where(x => x.OrganizationId == organizationId);
        if (!string.IsNullOrWhiteSpace(actionType)) q = q.Where(x => x.ActionType == actionType);
        if (from is not null) q = q.Where(x => x.CreatedAt >= from);
        if (to is not null) q = q.Where(x => x.CreatedAt <= to);
        var total = await q.CountAsync(ct);
        var orgNames = await _db.Organizations.IgnoreQueryFilters()
            .ToDictionaryAsync(o => o.Id, o => o.Name, ct);
        var items = await q
            .OrderByDescending(x => x.CreatedAt)
            .Skip(req.Skip).Take(req.Take)
            .ToListAsync(ct);
        var rows = items.Select(x => new AuditRow(
            x.Id, x.CreatedAt, x.SuperAdminUserId,
            x.ActionType, x.OrganizationId,
            x.OrganizationId is not null && orgNames.TryGetValue(x.OrganizationId.Value, out var n) ? n : null,
            x.EntityType, x.EntityId, x.Description, x.Reason, x.IpAddress)).ToList();
        return new PagedResult<AuditRow> { Items = rows, Total = total, Page = req.Page, PageSize = req.Take };
    }
}
