using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace StellaOps.Authority.Storage.Mongo.Documents;

/// <summary>
/// Represents a bootstrap invitation token for provisioning users or clients.
/// </summary>
[BsonIgnoreExtraElements]
public sealed class AuthorityBootstrapInviteDocument
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; } = ObjectId.GenerateNewId().ToString();

    [BsonElement("token")]
    public string Token { get; set; } = Guid.NewGuid().ToString("N");

    [BsonElement("type")]
    public string Type { get; set; } = "user";

    [BsonElement("provider")]
    [BsonIgnoreIfNull]
    public string? Provider { get; set; }

    [BsonElement("target")]
    [BsonIgnoreIfNull]
    public string? Target { get; set; }

    [BsonElement("issuedAt")]
    public DateTimeOffset IssuedAt { get; set; } = DateTimeOffset.UtcNow;

    [BsonElement("issuedBy")]
    [BsonIgnoreIfNull]
    public string? IssuedBy { get; set; }

    [BsonElement("expiresAt")]
    public DateTimeOffset ExpiresAt { get; set; } = DateTimeOffset.UtcNow.AddDays(2);

    [BsonElement("status")]
    public string Status { get; set; } = AuthorityBootstrapInviteStatuses.Pending;

    [BsonElement("reservedAt")]
    [BsonIgnoreIfNull]
    public DateTimeOffset? ReservedAt { get; set; }

    [BsonElement("reservedBy")]
    [BsonIgnoreIfNull]
    public string? ReservedBy { get; set; }

    [BsonElement("consumedAt")]
    [BsonIgnoreIfNull]
    public DateTimeOffset? ConsumedAt { get; set; }

    [BsonElement("consumedBy")]
    [BsonIgnoreIfNull]
    public string? ConsumedBy { get; set; }

    [BsonElement("metadata")]
    [BsonIgnoreIfNull]
    public Dictionary<string, string?>? Metadata { get; set; }
}

public static class AuthorityBootstrapInviteStatuses
{
    public const string Pending = "pending";
    public const string Reserved = "reserved";
    public const string Consumed = "consumed";
    public const string Expired = "expired";
}
