using Serilog;
using Serilog.Core;
using Serilog.Events;

namespace adas_core.Test.Models;

/// <summary>
/// Represents a fake implementation of the ILogger interface, typically used as a test double to simulate logging behavior.
/// </summary>
public class FakeLogger : ILogger
{
    public List<string> Messages { get; } = [];

    /// <summary>
    /// Creates a logger context enriched with the specified <see cref="ILogEventEnricher"/> instances. In this implementation, the enrichers are not applied and the current <see cref="ILogger"/> instance is returned unchanged.
    /// </summary>
    /// <param name="enrichers">The collection of enrichers intended to add contextual properties to log events.</param>
    /// <returns>The current <see cref="ILogger"/> instance, without the supplied enrichers applied.</returns>
    public ILogger ForContext(IEnumerable<ILogEventEnricher> enrichers)
    {
        return this;
    }

    /// <summary>
    /// Creates a logger context enriched with the specified property and value, returning the same logger instance.
    /// </summary>
    /// <param name="propertyName">The name of the property to add to the logger context.</param>
    /// <param name="value">The value associated with the property. Can be null.</param>
    /// <param name="destructureObjects">Indicates whether complex objects should be destructured. Defaults to false.</param>
    /// <returns>The current <see cref="ILogger"/> instance.</returns>
    public ILogger ForContext(string propertyName, object? value, bool destructureObjects = false)
    {
        return this;
    }

    /// <summary>
    /// Creates a logger context associated with the specified source type by returning the current <see cref="ILogger"/> instance.
    /// </summary>
    /// <typeparam name="TSource">The source type used to enrich the logger context.</typeparam>
    /// <returns>The current <see cref="ILogger"/> instance.</returns>
    public ILogger ForContext<TSource>()
    {
        return this;
    }

    /// <summary>
    /// Returns the current logger instance, ignoring the provided source type. Provides a no-op context enrichment for log messages.
    /// </summary>
    /// <param name="source">The source type used to enrich the logger context.</param>
    /// <returns>The current <see cref="ILogger"/> instance.</returns>
    public ILogger ForContext(Type source)
    {
        return this;
    }

    /// <summary>
    /// Appends the rendered message of the provided log event to the internal messages collection.
    /// </summary>
    /// <param name="logEvent">The log event whose rendered message will be added to the collection.</param>
    public void Write(LogEvent logEvent)
    {
        Messages.Add(logEvent.RenderMessage());
    }

    /// <summary>
    /// Writes a log message at the specified level to the internal messages collection, formatting it with the provided property values.
    /// </summary>
    /// <param name="level">The severity level of the log event.</param>
    /// <param name="messageTemplate">The message template containing placeholders for the property values.</param>
    /// <param name="propertyValues">An optional array of objects to format the message template. Can be <see langword="null"/>.</param>
    public void Write(LogEventLevel level, string messageTemplate, params object?[]? propertyValues)
    {
        // Manejar la situación donde propertyValues es nulo, si es necesario
        Messages.Add(propertyValues == null
            ? messageTemplate
            : string.Format(messageTemplate, propertyValues)); // Por ejemplo, solo añadir el mensaje sin formato
    }


    /// <summary>
    /// Writes a log entry by formatting the provided message template with the given property value and adding it to the messages collection.
    /// </summary>
    /// <typeparam name="T">The type of the property value to be substituted into the message template.</typeparam>
    /// <param name="level">The log event level associated with the entry being written.</param>
    /// <param name="messageTemplate">The message template containing a format placeholder for the property value.</param>
    /// <param name="propertyValue">The value to be inserted into the message template.</param>
    public void Write<T>(LogEventLevel level, string messageTemplate, T propertyValue)
    {
        Messages.Add(string.Format(messageTemplate, propertyValue));
    }


    /// <summary>
    /// Captures a log entry by appending the formatted message to the internal <c>Messages</c> collection.
    /// When <paramref name="propertyValues"/> is provided, the <paramref name="messageTemplate"/> is formatted with those values; otherwise the template is stored as-is.
    /// If <paramref name="exception"/> is not null, its message is appended as an additional entry.
    /// </summary>
    /// <param name="level">The severity level of the log event.</param>
    /// <param name="exception">An optional exception whose message is recorded when not null.</param>
    /// <param name="messageTemplate">The message template to log, used directly when <paramref name="propertyValues"/> is null.</param>
    /// <param name="propertyValues">Optional values to substitute into <paramref name="messageTemplate"/> via <c>string.Format</c>.</param>
    public void Write(LogEventLevel level, Exception? exception, string messageTemplate,
            params object?[]? propertyValues)
    {
        Messages.Add(propertyValues == null ? messageTemplate : string.Format(messageTemplate, propertyValues));

        if (exception != null) Messages.Add($"Exception: {exception.Message}");
    }


    /// <summary>
    /// Determines whether logging is enabled for the specified log event level. Currently returns <c>true</c> unconditionally, allowing all log levels to be processed.
    /// </summary>
    /// <param name="level">The log event level to evaluate.</param>
    /// <returns><c>true</c> if logging is enabled for the given level; otherwise, <c>false</c>.</returns>
    public bool IsEnabled(LogEventLevel level)
    {
        return true;
    }

    /// <summary>
    /// Writes a log entry by formatting the provided message template with the supplied property value and appending it to the Messages collection. If an exception is supplied, its message is also appended to the collection.
    /// </summary>
    /// <param name="level">The severity level of the log event.</param>
    /// <param name="exception">An optional exception whose message, when not null, is added to the Messages collection after the formatted message.</param>
    /// <param name="messageTemplate">The message template string used to format the log entry.</param>
    /// <param name="propertyValue">The value to be substituted into the message template.</param>
    public void Write<T>(LogEventLevel level, Exception? exception, string messageTemplate, T propertyValue)
    {
        Messages.Add(string.Format(messageTemplate, propertyValue));
        if (exception != null)
            Messages.Add($"Exception: {exception.Message}"); // You might want to include the exception here.
    }
}