using System.Globalization;
using System.Security.Cryptography;
using System.Text.Json.Nodes;
using Eis.Application.Administration;
using Eis.Infrastructure.Authentication;
using Eis.Infrastructure.Candidate;

namespace Eis.Infrastructure.Administration;

internal sealed class AdminCenterService(
    IAuthenticationStateStore authenticationState,
    AuthenticationRepository authenticationRepository,
    RegionCatalog regionCatalog,
    AdminAccountBatchSnapshotLoader workflowSnapshotLoader,
    AdminCenterSnapshotLoader centerSnapshotLoader,
    AdminCenterRepository repository) : IAdminCenterService
{
    private static readonly IReadOnlyDictionary<string, string> LevelNames = new Dictionary<string, string>(StringComparer.Ordinal)
    {
        ["super"] = "超级管理员",
        ["school"] = "校级管理员",
        ["class"] = "班级管理员"
    };

    public async Task<AdminEndpointResult> GetAsync(string sessionToken, CancellationToken cancellationToken)
    {
        var context = await ResolveAsync(sessionToken, cancellationToken);
        if (context.Error is not null) return context.Error;
        var user = context.User!;
        if (!CanManageCenters(user)) return Error(403, "当前管理员层级无权执行此操作");
        var workflow = await workflowSnapshotLoader.LoadAsync(cancellationToken);
        var centers = await centerSnapshotLoader.LoadAsync(cancellationToken);
        var visibleCenters = centers.Centers.Where(item => Level(user) == "super" || item.SchoolId == user.SchoolId)
            .Select(item => CenterJson(workflow, centers, item)).ToArray();
        var changes = centers.Changes.Where(item => Level(user) == "super" || item.SchoolId == user.SchoolId)
            .Select(item => ChangeJson(workflow, centers, item)).ToArray();
        var schools = workflow.Schools.Where(item => Level(user) == "super" || item.Id == user.SchoolId)
            .Select(SchoolJson).ToArray();
        return Success(new JsonObject
        {
            ["ok"] = true,
            ["centers"] = new JsonArray(visibleCenters),
            ["changeRequests"] = new JsonArray(changes),
            ["schools"] = new JsonArray(schools)
        });
    }

    public async Task<AdminEndpointResult> CreateAsync(
        string sessionToken,
        JsonObject body,
        CancellationToken cancellationToken)
    {
        var context = await ResolveAsync(sessionToken, cancellationToken);
        if (context.Error is not null) return context.Error;
        var user = context.User!;
        if (!CanManageCenters(user)) return Error(403, "当前管理员层级无权执行此操作");
        var workflow = await workflowSnapshotLoader.LoadAsync(cancellationToken);
        var centers = await centerSnapshotLoader.LoadAsync(cancellationToken);
        var schoolId = Level(user) == "super" ? Clean(Text(body["schoolId"]), 64) : user.SchoolId ?? "";
        if (!workflow.Schools.Any(item => item.Id == schoolId)) return Error(400, "考点必须归属有效学校");
        var parsed = Parse(body, schoolId, null, centers);
        if (parsed.Error is not null) return parsed.Error;
        return await SubmitAsync(user, workflow, centers, parsed.Value!, null, "create", cancellationToken);
    }

    public async Task<AdminEndpointResult> UpdateAsync(
        string sessionToken,
        string centerId,
        JsonObject body,
        CancellationToken cancellationToken)
    {
        var context = await ResolveAsync(sessionToken, cancellationToken);
        if (context.Error is not null) return context.Error;
        var user = context.User!;
        if (!CanManageCenters(user)) return Error(403, "当前管理员层级无权执行此操作");
        var workflow = await workflowSnapshotLoader.LoadAsync(cancellationToken);
        var centers = await centerSnapshotLoader.LoadAsync(cancellationToken);
        var center = centers.Centers.FirstOrDefault(item => item.Id == centerId);
        if (center is null) return Error(404, "考点不存在");
        if (Level(user) != "super" && center.SchoolId != user.SchoolId) return Error(403, "只能维护本校考点");
        if (centers.Changes.Any(item => item.CenterId == center.Id && item.Status == "pending"))
        {
            return Error(409, "该考点已有待审批变更，请处理完成后再提交");
        }
        var parsed = Parse(body, center.SchoolId, center, centers);
        if (parsed.Error is not null) return parsed.Error;
        return await SubmitAsync(user, workflow, centers, parsed.Value!, center.Id, "update", cancellationToken);
    }

    public async Task<AdminEndpointResult> ReviewAsync(
        string sessionToken,
        string changeRequestId,
        JsonObject body,
        CancellationToken cancellationToken)
    {
        var context = await ResolveAsync(sessionToken, cancellationToken);
        if (context.Error is not null) return context.Error;
        var user = context.User!;
        if (!CanManageCenters(user)) return Error(403, "当前管理员层级无权执行此操作");
        var status = Text(body["status"]);
        if (status is not ("approved" or "rejected")) return Error(400, "审批状态无效");
        var workflow = await workflowSnapshotLoader.LoadAsync(cancellationToken);
        var centers = await centerSnapshotLoader.LoadAsync(cancellationToken);
        var change = centers.Changes.FirstOrDefault(item => item.Id == changeRequestId && item.Status == "pending");
        if (change is null) return Error(404, "待审批的考点变更不存在");
        if (Level(user) != "super" && change.SchoolId != user.SchoolId) return Error(403, "该变更不在你的学校范围内");
        var instance = workflow.Instances.FirstOrDefault(item =>
            item.BusinessType == "center_change" && item.BusinessId == change.Id && item.Status == "pending");
        var definition = workflow.Workflows.FirstOrDefault(item => item.Id == instance?.WorkflowId);
        var step = definition?.Steps.FirstOrDefault(item => item.Position == instance?.CurrentStep);
        if (instance is null || definition is null || step is null) return Error(409, "考点变更审批流程状态异常");
        if (Level(user) != "super" && (instance.AssigneeId != user.Id || step.AdminLevel != Level(user)))
        {
            return Error(403, "该流程当前未分配给你，可由当前处理人转交");
        }
        var note = Clean(Text(body["reviewNote"]), 300);
        var action = new AccountWorkflowAction(
            Uid("flow_action"), instance.Id, user.Id, status == "approved" ? "approve" : "reject", note,
            instance.AssigneeId, null, NowIso());
        var audit = Audit(
            user,
            status == "approved" ? "审批考点变更" : "退回考点变更",
            $"{change.Name} · {(note.Length == 0 ? "无备注" : note)}");

        if (status == "rejected")
        {
            var rejectedAt = NowIso();
            var rejectedChange = change with { Status = "rejected", ReviewNote = note, ReviewedAt = rejectedAt };
            var rejectedInstance = instance with { Status = "rejected", AssigneeId = null, CompletedAt = rejectedAt };
            await repository.ProcessAsync(rejectedChange, rejectedInstance, action, audit, cancellationToken);
            return Success(new JsonObject
            {
                ["ok"] = true,
                ["changeRequest"] = ChangeJson(workflow, centers, rejectedChange, rejectedInstance, [action])
            });
        }

        if (instance.CurrentStep < definition.Steps.Count)
        {
            var nextStep = definition.Steps.First(item => item.Position == instance.CurrentStep + 1);
            var nextAssignee = SelectAssignee(workflow, nextStep.AdminLevel, change.SchoolId);
            if (nextAssignee is null) return Error(409, $"没有可承接“{nextStep.Name}”的管理员");
            var advancedInstance = instance with { CurrentStep = instance.CurrentStep + 1, AssigneeId = nextAssignee.Id };
            var advancedAction = action with { ToAssigneeId = nextAssignee.Id };
            var advancedChange = change with { ReviewNote = note };
            await repository.ProcessAsync(advancedChange, advancedInstance, advancedAction, audit, cancellationToken);
            return Success(new JsonObject
            {
                ["ok"] = true,
                ["changeRequest"] = ChangeJson(workflow, centers, advancedChange, advancedInstance, [advancedAction])
            });
        }

        var completedAt = NowIso();
        var completedChange = change with { Status = "approved", ReviewNote = note, ReviewedAt = completedAt };
        var completedInstance = instance with { Status = "approved", AssigneeId = null, CompletedAt = completedAt };
        var centerId = change.CenterId ?? Uid("center");
        var proposedRooms = centers.ChangeRooms.Where(item => item.RequestId == change.Id).ToArray();
        var rooms = proposedRooms.Select(item => new AdminCenterRoom(
            item.RoomId ?? Uid("room"), centerId, item.Code, item.Name, item.Building, item.Floor, item.Capacity,
            item.SeatPlan, 1, item.Capacity, item.RoomType, item.Status, item.Notes)).ToArray();
        var center = new AdminCenter(
            centerId, change.SchoolId, change.Code, change.Name, change.ProvinceCode, change.ProvinceName,
            change.CityCode, change.CityName, change.DistrictCode, change.DistrictName, change.Address, change.Contact,
            change.ManagerName, change.ManagerPhone, change.EmergencyPhone, change.GateOpenTime, change.Transport,
            change.CenterStatus, change.Notes, string.Join("；", rooms.Select(item => $"{item.Building} {item.Name}")), NowIso());
        await repository.ApplyAsync(completedChange, completedInstance, action, center, rooms, audit, cancellationToken);
        return Success(new JsonObject
        {
            ["ok"] = true,
            ["changeRequest"] = ChangeJson(workflow, centers, completedChange, completedInstance, [action])
        });
    }

    private async Task<AdminEndpointResult> SubmitAsync(
        AuthenticationUser user,
        AdminAccountBatchSnapshot workflow,
        AdminCenterSnapshot centers,
        ParsedCenter parsed,
        string? centerId,
        string requestType,
        CancellationToken cancellationToken)
    {
        var definition = workflow.Workflows.FirstOrDefault(item => item.BusinessType == "center_change" && item.Active);
        if (definition is null || definition.Steps.Count == 0) return Error(409, "该业务尚未配置审批流程");
        var firstStep = definition.Steps[0];
        var assignee = SelectAssignee(workflow, firstStep.AdminLevel, parsed.SchoolId);
        if (assignee is null) return Error(409, $"没有可承接“{firstStep.Name}”的{LevelNames[firstStep.AdminLevel]}");
        var now = NowIso();
        var changeId = Uid("center_change");
        var change = new AdminCenterChange(
            changeId, centerId, parsed.SchoolId, requestType, parsed.Code, parsed.Name,
            parsed.ProvinceCode, parsed.ProvinceName, parsed.CityCode, parsed.CityName, parsed.DistrictCode, parsed.DistrictName,
            parsed.Address, parsed.Contact, parsed.ManagerName, parsed.ManagerPhone, parsed.EmergencyPhone,
            parsed.GateOpenTime, parsed.Transport, parsed.Status, parsed.Notes, "pending", "", user.Id, now, null);
        var rooms = parsed.Rooms.Select(item => item with { RequestId = changeId }).ToArray();
        var instance = new AccountWorkflowInstance(
            Uid("flow"), definition.Id, "center_change", change.Id, "pending", 1, assignee.Id, NowIso(), null);
        var action = new AccountWorkflowAction(
            Uid("flow_action"), instance.Id, user.Id, "submit", "提交审批", null, assignee.Id, NowIso());
        var auditAction = requestType == "create" ? "提交新增考点审批" : "提交考点变更审批";
        await repository.CreateRequestAsync(
            change, rooms, instance, action,
            Audit(user, auditAction, $"{change.Name} · {rooms.Length} 个考场"), cancellationToken);
        return Result(202, new JsonObject
        {
            ["ok"] = true,
            ["changeRequest"] = ChangeJson(workflow, centers, change, instance, [action], rooms)
        });
    }

    private ParsedResult Parse(JsonObject body, string schoolId, AdminCenter? existing, AdminCenterSnapshot snapshot)
    {
        var code = Clean(Text(body["code"]), 30).ToUpperInvariant();
        var name = Clean(Text(body["name"]), 100);
        var address = Clean(Text(body["address"]), 200);
        var region = regionCatalog.Resolve(Text(body["provinceCode"]), Text(body["cityCode"]), Text(body["districtCode"]));
        if (code.Length == 0 || name.Length == 0 || address.Length == 0 || region is null)
        {
            return ParsedResult.Failed(Error(400, "请填写考点代码、名称、省市区县和详细地址"));
        }
        if (body["rooms"] is not JsonArray requestedRooms || requestedRooms.Count == 0)
        {
            return ParsedResult.Failed(Error(400, "请至少配置一个结构化考场"));
        }
        var duplicate = snapshot.Centers.Any(item => item.Code.Equals(code, StringComparison.OrdinalIgnoreCase) && item.Id != existing?.Id) ||
                        snapshot.Changes.Any(item => item.Status == "pending" && item.Code.Equals(code, StringComparison.OrdinalIgnoreCase) &&
                                                     (existing is null || item.CenterId != existing.Id));
        if (duplicate) return ParsedResult.Failed(Error(409, "考点代码已被正式档案或待审批申请占用"));
        var roomCodes = new HashSet<string>(StringComparer.Ordinal);
        var rooms = new List<AdminCenterChangeRoom>();
        for (var index = 0; index < requestedRooms.Count; index++)
        {
            if (requestedRooms[index] is not JsonObject room)
            {
                return ParsedResult.Failed(Error(400, $"第 {index + 1} 个考场的代码、名称、楼栋或容量无效"));
            }
            var roomCode = Clean(Text(room["code"]), 30).ToUpperInvariant();
            var roomName = Clean(Text(room["name"]), 80);
            var building = Clean(Text(room["building"]), 80);
            var capacity = Number(room["capacity"]);
            if (roomCode.Length == 0 || roomName.Length == 0 || building.Length == 0 || !double.IsInteger(capacity) || capacity < 1 || capacity > int.MaxValue)
            {
                return ParsedResult.Failed(Error(400, $"第 {index + 1} 个考场的代码、名称、楼栋或容量无效"));
            }
            if (!roomCodes.Add(roomCode)) return ParsedResult.Failed(Error(400, $"考场代码 {roomCode} 重复"));
            var integerCapacity = (int)capacity;
            var roomType = Text(room["roomType"]);
            rooms.Add(new AdminCenterChangeRoom(
                Uid("change_room"), "", Optional(Clean(Text(room["id"]), 64)), roomCode, roomName, building,
                Clean(Text(room["floor"]), 30), integerCapacity, Clean(Text(room["seatPlan"]), 500), 1, integerCapacity,
                roomType is "standard" or "computer" or "accessible" or "spare" ? roomType : "standard",
                Text(room["status"]) == "inactive" ? "inactive" : "active", Clean(Text(room["notes"]), 300)));
        }
        return ParsedResult.Succeeded(new ParsedCenter(
            schoolId, code, name, region.ProvinceCode, region.ProvinceName, region.CityCode, region.CityName,
            region.DistrictCode, region.DistrictName, address, Clean(Text(body["contact"]), 80),
            Clean(Text(body["managerName"]), 50), Clean(Text(body["managerPhone"]), 30),
            Clean(Text(body["emergencyPhone"]), 30), Clean(Text(body["gateOpenTime"]), 20),
            Clean(Text(body["transport"]), 500), Text(body["status"]) == "inactive" ? "inactive" : "active",
            Clean(Text(body["notes"]), 1000), rooms));
    }

    private static AdminUser? SelectAssignee(AdminAccountBatchSnapshot snapshot, string level, string schoolId)
    {
        var pending = snapshot.Instances.Where(item => item.Status == "pending" && item.AssigneeId is not null)
            .GroupBy(item => item.AssigneeId!).ToDictionary(group => group.Key, group => group.Count(), StringComparer.Ordinal);
        var assigned = snapshot.Actions.Where(item => item.ToAssigneeId is not null)
            .GroupBy(item => item.ToAssigneeId!).ToDictionary(group => group.Key, group => group.Count(), StringComparer.Ordinal);
        return snapshot.Users.Where(item => item.Role == "admin" && item.Active && item.AdminLevel == level &&
                                            (level == "super" || level == "school" && item.SchoolId == schoolId))
            .OrderBy(item => pending.GetValueOrDefault(item.Id))
            .ThenBy(item => assigned.GetValueOrDefault(item.Id))
            .ThenBy(item => item.CreatedAt, StringComparer.Ordinal)
            .ThenBy(item => item.Id, StringComparer.Ordinal)
            .FirstOrDefault();
    }

    private static JsonObject CenterJson(AdminAccountBatchSnapshot workflow, AdminCenterSnapshot snapshot, AdminCenter item)
    {
        var rooms = snapshot.Rooms.Where(room => room.CenterId == item.Id).Select(RoomJson).ToArray();
        return new JsonObject
        {
            ["id"] = item.Id,
            ["schoolId"] = item.SchoolId,
            ["code"] = item.Code,
            ["name"] = item.Name,
            ["provinceCode"] = item.ProvinceCode,
            ["provinceName"] = item.ProvinceName,
            ["cityCode"] = item.CityCode,
            ["cityName"] = item.CityName,
            ["districtCode"] = item.DistrictCode,
            ["districtName"] = item.DistrictName,
            ["address"] = item.Address,
            ["contact"] = item.Contact,
            ["managerName"] = item.ManagerName,
            ["managerPhone"] = item.ManagerPhone,
            ["emergencyPhone"] = item.EmergencyPhone,
            ["gateOpenTime"] = item.GateOpenTime,
            ["transport"] = item.Transport,
            ["status"] = item.Status,
            ["notes"] = item.Notes,
            ["rooms"] = new JsonArray(rooms),
            ["updatedAt"] = item.UpdatedAt,
            ["schoolName"] = workflow.Schools.FirstOrDefault(school => school.Id == item.SchoolId)?.Name ?? "",
            ["totalCapacity"] = snapshot.Rooms.Where(room => room.CenterId == item.Id && room.Status == "active").Sum(room => room.Capacity),
            ["pendingChange"] = snapshot.Changes.Any(change => change.CenterId == item.Id && change.Status == "pending")
        };
    }

    internal static JsonObject ChangeJson(
        AdminAccountBatchSnapshot workflow,
        AdminCenterSnapshot centers,
        AdminCenterChange item,
        AccountWorkflowInstance? instanceOverride = null,
        IReadOnlyList<AccountWorkflowAction>? extraActions = null,
        IReadOnlyList<AdminCenterChangeRoom>? roomOverride = null)
    {
        var rooms = (roomOverride ?? centers.ChangeRooms.Where(room => room.RequestId == item.Id).ToArray())
            .Select(ChangeRoomJson).ToArray();
        var instance = instanceOverride ?? workflow.Instances.FirstOrDefault(entry => entry.BusinessType == "center_change" && entry.BusinessId == item.Id);
        return new JsonObject
        {
            ["id"] = item.Id,
            ["centerId"] = JsonValue.Create(item.CenterId),
            ["schoolId"] = item.SchoolId,
            ["requestType"] = item.RequestType,
            ["code"] = item.Code,
            ["name"] = item.Name,
            ["provinceCode"] = item.ProvinceCode,
            ["provinceName"] = item.ProvinceName,
            ["cityCode"] = item.CityCode,
            ["cityName"] = item.CityName,
            ["districtCode"] = item.DistrictCode,
            ["districtName"] = item.DistrictName,
            ["address"] = item.Address,
            ["contact"] = item.Contact,
            ["managerName"] = item.ManagerName,
            ["managerPhone"] = item.ManagerPhone,
            ["emergencyPhone"] = item.EmergencyPhone,
            ["gateOpenTime"] = item.GateOpenTime,
            ["transport"] = item.Transport,
            ["centerStatus"] = item.CenterStatus,
            ["notes"] = item.Notes,
            ["status"] = item.Status,
            ["reviewNote"] = item.ReviewNote,
            ["requestedBy"] = JsonValue.Create(item.RequestedBy),
            ["createdAt"] = item.CreatedAt,
            ["reviewedAt"] = JsonValue.Create(item.ReviewedAt),
            ["schoolName"] = workflow.Schools.FirstOrDefault(school => school.Id == item.SchoolId)?.Name ?? "",
            ["rooms"] = new JsonArray(rooms),
            ["workflow"] = instance is null ? null : WorkflowJson(workflow, instance, extraActions)
        };
    }

    private static JsonObject WorkflowJson(
        AdminAccountBatchSnapshot snapshot,
        AccountWorkflowInstance instance,
        IReadOnlyList<AccountWorkflowAction>? extraActions)
    {
        var workflow = snapshot.Workflows.FirstOrDefault(item => item.Id == instance.WorkflowId);
        var assignee = snapshot.Users.FirstOrDefault(item => item.Id == instance.AssigneeId);
        var actions = snapshot.Actions.Where(item => item.InstanceId == instance.Id).Concat(extraActions ?? [])
            .Select(item => ActionJson(snapshot, item)).ToArray();
        return new JsonObject
        {
            ["id"] = instance.Id,
            ["workflowId"] = instance.WorkflowId,
            ["businessType"] = instance.BusinessType,
            ["businessId"] = instance.BusinessId,
            ["status"] = instance.Status,
            ["currentStep"] = instance.CurrentStep,
            ["assigneeId"] = JsonValue.Create(instance.AssigneeId),
            ["createdAt"] = instance.CreatedAt,
            ["completedAt"] = JsonValue.Create(instance.CompletedAt),
            ["workflowName"] = workflow?.Name ?? "未命名流程",
            ["steps"] = new JsonArray((workflow?.Steps ?? []).Select(StepJson).ToArray()),
            ["currentStepDetail"] = workflow?.Steps.FirstOrDefault(item => item.Position == instance.CurrentStep) is { } step ? StepJson(step) : null,
            ["assignee"] = assignee is null ? null : SafeUser(assignee),
            ["actions"] = new JsonArray(actions)
        };
    }

    private async Task<ResolvedAdmin> ResolveAsync(string token, CancellationToken cancellationToken)
    {
        if (token.Length == 0) return ResolvedAdmin.Failed(Error(401, "请先登录"));
        var userId = await authenticationState.GetSessionUserIdAsync(token);
        if (userId is null) return ResolvedAdmin.Failed(Error(401, "请先登录"));
        var user = await authenticationRepository.FindUserByIdAsync(userId, cancellationToken);
        if (user is not { Active: true, ArchivedAt: null }) return ResolvedAdmin.Failed(Error(401, "请先登录"));
        return user.Role == "admin" ? new(user, null) : ResolvedAdmin.Failed(Error(403, "当前账号无权执行此操作"));
    }

    private static JsonObject RoomJson(AdminCenterRoom item) => new()
    {
        ["id"] = item.Id,
        ["centerId"] = item.CenterId,
        ["code"] = item.Code,
        ["name"] = item.Name,
        ["building"] = item.Building,
        ["floor"] = item.Floor,
        ["capacity"] = item.Capacity,
        ["seatPlan"] = item.SeatPlan,
        ["seatStart"] = item.SeatStart,
        ["seatEnd"] = item.SeatEnd,
        ["roomType"] = item.RoomType,
        ["status"] = item.Status,
        ["notes"] = item.Notes
    };

    private static JsonObject ChangeRoomJson(AdminCenterChangeRoom item) => new()
    {
        ["id"] = item.Id,
        ["requestId"] = item.RequestId,
        ["roomId"] = JsonValue.Create(item.RoomId),
        ["code"] = item.Code,
        ["name"] = item.Name,
        ["building"] = item.Building,
        ["floor"] = item.Floor,
        ["capacity"] = item.Capacity,
        ["seatPlan"] = item.SeatPlan,
        ["seatStart"] = item.SeatStart,
        ["seatEnd"] = item.SeatEnd,
        ["roomType"] = item.RoomType,
        ["status"] = item.Status,
        ["notes"] = item.Notes
    };

    private static JsonObject SchoolJson(AdminSchool item) => new()
    {
        ["id"] = item.Id,
        ["name"] = item.Name,
        ["code"] = item.Code,
        ["address"] = item.Address,
        ["isSourceSchool"] = item.IsSourceSchool,
        ["isAdmissionSchool"] = item.IsAdmissionSchool,
        ["active"] = item.Active
    };

    private static JsonObject StepJson(AccountWorkflowStep item) => new()
    {
        ["id"] = item.Id,
        ["position"] = item.Position,
        ["name"] = item.Name,
        ["adminLevel"] = item.AdminLevel
    };

    private static JsonObject ActionJson(AdminAccountBatchSnapshot snapshot, AccountWorkflowAction item) => new()
    {
        ["id"] = item.Id,
        ["instanceId"] = item.InstanceId,
        ["actorId"] = JsonValue.Create(item.ActorId),
        ["action"] = item.Action,
        ["note"] = item.Note,
        ["fromAssigneeId"] = JsonValue.Create(item.FromAssigneeId),
        ["toAssigneeId"] = JsonValue.Create(item.ToAssigneeId),
        ["createdAt"] = item.CreatedAt,
        ["actorName"] = snapshot.Users.FirstOrDefault(user => user.Id == item.ActorId)?.DisplayName ?? "系统",
        ["fromAssigneeName"] = snapshot.Users.FirstOrDefault(user => user.Id == item.FromAssigneeId)?.DisplayName ?? "",
        ["toAssigneeName"] = snapshot.Users.FirstOrDefault(user => user.Id == item.ToAssigneeId)?.DisplayName ?? ""
    };

    private static JsonObject SafeUser(AdminUser item) => new()
    {
        ["id"] = item.Id,
        ["username"] = item.Username,
        ["role"] = item.Role,
        ["adminLevel"] = item.Role == "admin" ? item.AdminLevel ?? "super" : null,
        ["schoolId"] = JsonValue.Create(item.SchoolId),
        ["classId"] = JsonValue.Create(item.ClassId),
        ["displayName"] = item.DisplayName,
        ["candidateNumber"] = JsonValue.Create(item.CandidateNumber),
        ["mustChangePassword"] = item.MustChangePassword,
        ["totpEnabled"] = item.TotpEnabled,
        ["archived"] = item.ArchivedAt is not null
    };

    private static double Number(JsonNode? node) =>
        double.TryParse(Text(node), NumberStyles.Float, CultureInfo.InvariantCulture, out var value) ? value : double.NaN;

    private static string Text(JsonNode? node) =>
        node is JsonValue value && value.TryGetValue<string>(out var text) ? text : node?.ToString() ?? "";

    private static string Clean(string value, int maximum)
    {
        var cleaned = value.Trim();
        return cleaned[..Math.Min(cleaned.Length, maximum)];
    }

    private static string? Optional(string value) => value.Length == 0 ? null : value;
    private static bool CanManageCenters(AuthenticationUser user) => Level(user) is "super" or "school";
    private static string Level(AuthenticationUser user) => user.AdminLevel ?? "super";
    private static string NowIso() => DateTimeOffset.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'", CultureInfo.InvariantCulture);
    private static string Uid(string prefix) => $"{prefix}_{ToBase36(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())}_{Convert.ToHexStringLower(RandomNumberGenerator.GetBytes(4))}";
    private static string ToBase36(long value) { const string alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"; Span<char> buffer = stackalloc char[16]; var position = buffer.Length; do { buffer[--position] = alphabet[(int)(value % 36)]; value /= 36; } while (value > 0); return new(buffer[position..]); }
    private static AdminAuditEntry Audit(AuthenticationUser user, string action, string detail) => new(Uid("log"), user.Id, action, detail, NowIso());
    private static AdminEndpointResult Success(JsonObject body) => Result(200, body);
    private static AdminEndpointResult Result(int status, JsonObject body) => new(status, body);
    private static AdminEndpointResult Error(int status, string message) => Result(status, new JsonObject { ["ok"] = false, ["message"] = message });

    private sealed record ParsedCenter(
        string SchoolId,
        string Code,
        string Name,
        string ProvinceCode,
        string ProvinceName,
        string CityCode,
        string CityName,
        string DistrictCode,
        string DistrictName,
        string Address,
        string Contact,
        string ManagerName,
        string ManagerPhone,
        string EmergencyPhone,
        string GateOpenTime,
        string Transport,
        string Status,
        string Notes,
        IReadOnlyList<AdminCenterChangeRoom> Rooms);

    private sealed record ParsedResult(ParsedCenter? Value, AdminEndpointResult? Error)
    {
        public static ParsedResult Succeeded(ParsedCenter value) => new(value, null);
        public static ParsedResult Failed(AdminEndpointResult error) => new(null, error);
    }

    private sealed record ResolvedAdmin(AuthenticationUser? User, AdminEndpointResult? Error)
    {
        public static ResolvedAdmin Failed(AdminEndpointResult error) => new(null, error);
    }
}
