using System;
using System.Collections.Generic;

namespace EonaCat.LogStack.Tracing
{
    /// <summary>
    /// Represents a trace context for distributed tracing across async boundaries.
    /// Contains trace ID, span ID, parent span ID, and baggage for propagation.
    /// </summary>
    public sealed class TraceContext
    {
        /// <summary>
        /// Gets or sets the trace ID (root identifier for entire trace)
        /// </summary>
        public string TraceId { get; set; }

        /// <summary>
        /// Gets or sets the span ID (current operation identifier)
        /// </summary>
        public string SpanId { get; set; }

        /// <summary>
        /// Gets or sets the parent span ID (parent operation identifier, if any)
        /// </summary>
        public string? ParentSpanId { get; set; }

        /// <summary>
        /// Gets or sets the correlation ID for request tracking
        /// </summary>
        public string? CorrelationId { get; set; }

        /// <summary>
        /// Gets or sets baggage (key-value pairs to propagate across spans)
        /// </summary>
        public Dictionary<string, string> Baggage { get; set; } = new();

        /// <summary>
        /// Gets or sets the trace flags (e.g., sampling decision)
        /// </summary>
        public byte TraceFlags { get; set; } = 0x01;

        /// <summary>
        /// Gets the creation timestamp
        /// </summary>
        public DateTime CreatedAt { get; } = DateTime.UtcNow;

        /// <summary>
        /// Gets whether this trace is sampled for export
        /// </summary>
        public bool IsSampled => (TraceFlags & 0x01) != 0;

        /// <summary>
        /// Creates a new TraceContext with a generated trace ID
        /// </summary>
        public TraceContext()
        {
            TraceId = GenerateId();
            SpanId = GenerateId();
        }

        /// <summary>
        /// Creates a child TraceContext from this context
        /// </summary>
        public TraceContext CreateChild()
        {
            return new TraceContext
            {
                TraceId = TraceId,
                ParentSpanId = SpanId,
                SpanId = GenerateId(),
                CorrelationId = CorrelationId,
                TraceFlags = TraceFlags,
                Baggage = new Dictionary<string, string>(Baggage)
            };
        }

        /// <summary>
        /// Generates a random ID for trace/span
        /// </summary>
        private static string GenerateId()
        {
            return Guid.NewGuid().ToString("N").Substring(0, 16);
        }

        /// <summary>
        /// Creates a copy of this TraceContext for propagation
        /// </summary>
        public TraceContext Clone()
        {
            return new TraceContext
            {
                TraceId = TraceId,
                SpanId = SpanId,
                ParentSpanId = ParentSpanId,
                CorrelationId = CorrelationId,
                TraceFlags = TraceFlags,
                Baggage = new Dictionary<string, string>(Baggage)
            };
        }
    }
}
