using System.Text;

namespace audit.Model;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;

public class AuditRecord
{
    [BsonId]
    public ObjectId Id { get; set; }

    [BsonElement("entity_type")]
    public string EntityType { get; set; }

    [BsonElement("record_id")]
    public string RecordId { get; set; }

    [BsonElement("user_id")]
    public string UserId { get; set; }

    [BsonElement("action_type")]
    public string ActionType { get; set; }

    [BsonElement("action_time")]
    public DateTime ActionTime { get; set; }

    [BsonElement("changes")]
    public List<Change> Changes { get; set; }

    [BsonElement("reason")]
    public string Reason { get; set; }

    [BsonElement("user_ip_address")]
    public string? UserIpAddress { get; set; }
    

    
    public override string ToString()
    {
        var changesBuilder = new StringBuilder();
        foreach (var change in Changes)
        {
            changesBuilder.AppendLine($"Field: {change.Field}, Old Value: {FormatBsonValue(change.OldValue)}, New Value: {FormatBsonValue(change.NewValue)}, Value Type: {change.ValueType}");
        }

        return $"ID: {Id}, Entity Type: {EntityType}, Record ID: {RecordId}, User ID: {UserId}, Action Type: {ActionType}, Action Time: {ActionTime}, Reason: {Reason}, User IP: {UserIpAddress}, Changes: {changesBuilder.ToString()}";
    }
    
    private string FormatBsonValue(BsonValue value)
    {
        if (value == null || value.IsBsonNull)
        {
            return "null";
        }

        switch (value.BsonType)
        {
            case BsonType.Array:
                var array = new StringBuilder("[");
                foreach (var item in value.AsBsonArray)
                {
                    array.Append(FormatBsonValue(item) + ", ");
                }
                if (array.Length > 1)
                {
                    array.Length -= 2; // Remove the last comma and space
                }
                array.Append("]");
                return array.ToString();
            case BsonType.Document:
                var document = new StringBuilder("{");
                foreach (var element in value.AsBsonDocument)
                {
                    document.Append(element.Name + ": " + FormatBsonValue(element.Value) + ", ");
                }
                if (document.Length > 1)
                {
                    document.Length -= 2; // Remove the last comma and space
                }
                document.Append("}");
                return document.ToString();
            default:
                return value.ToString(); // Use default BsonValue's ToString for other types
        }
    }

    
    

    public class Change
    {
        [BsonElement("field")]
        public string Field { get; set; }

        [BsonElement("old_value")]
        public BsonValue OldValue { get; set; }

        [BsonElement("new_value")]
        public BsonValue NewValue { get; set; }

        [BsonElement("value_type")]
        public string ValueType { get; set; }

        public static object ConvertBsonValue(BsonValue bsonValue)
        {
            if (bsonValue == null || bsonValue.IsBsonNull)
            {
                return null; // Devuelve nulo si el valor BSON es nulo o no existe
            }
            switch (bsonValue.BsonType)
            {
                case BsonType.String:
                    return bsonValue.AsString;
                case BsonType.Int32:
                    return bsonValue.AsInt32;
                case BsonType.Int64:
                    return bsonValue.AsInt64;
                case BsonType.Boolean:
                    return bsonValue.AsBoolean;
                case BsonType.DateTime:
                    return bsonValue.ToUniversalTime();
                case BsonType.Double:
                    return bsonValue.AsDouble;
                case BsonType.ObjectId:
                    return bsonValue.AsObjectId.ToString();
                /*case BsonType.Document:
                    return bsonValue.ToJson(); */
                case BsonType.Array:
                    var array = bsonValue.AsBsonArray;
                    var resultList = new List<object>();
                    foreach (var item in array)
                    {
                        resultList.Add(ConvertBsonValue(item));  
                    }
                    return resultList;
                case BsonType.Document:
                    // Convert BSON Document to Dictionary
                    var document = bsonValue.AsBsonDocument;
                    var dictionary = new Dictionary<string, object>();
                    foreach (var element in document)
                    {
                        dictionary[element.Name] = ConvertBsonValue(element.Value); 
                    }
                    return dictionary;

                default:
                    return bsonValue.ToJson(); // Convert to string if type is not directly supported
            }
        }
       
    }

   
}
