namespace AyCode.Core.Serializers.Toons;

/// <summary>
/// Controls what sections are included in Toon serialization output.
/// </summary>
public enum ToonSerializationMode : byte
{
    /// <summary>
    /// Include both @meta/@types and @data sections (default).
    /// Best for first-time serialization or when LLM needs full context.
    /// </summary>
    Full = 0,

    /// <summary>
    /// Only include @meta and @types sections, no @data.
    /// Use to send schema/documentation once at the start of conversation.
    /// </summary>
    MetaOnly = 1,

    /// <summary>
    /// Only include @data section, no @meta/@types.
    /// Use when schema was already sent via MetaOnly - saves tokens.
    /// </summary>
    DataOnly = 2
}

/// <summary>
/// Options for AcToonSerializer - Token-Oriented Object Notation.
/// Optimized for LLM readability and token efficiency.
/// </summary>
public sealed class AcToonSerializerOptions : AcSerializerOptions
{
    public override AcSerializerType SerializerType { get; init; } = AcSerializerType.Toon;

    // === META CONTROL ===

    /// <summary>
    /// Whether to include type metadata (schema, descriptions, constraints).
    /// When true, @types section is included with full documentation.
    /// Default: true
    /// </summary>
    public bool UseMeta { get; init; } = true;

    /// <summary>
    /// Serialization mode - controls what gets serialized.
    /// Full = meta + data, MetaOnly = only schema, DataOnly = only values.
    /// Default: Full
    /// </summary>
    public ToonSerializationMode Mode { get; init; } = ToonSerializationMode.Full;

    // === FORMATTING ===

    /// <summary>
    /// Use indentation for readability.
    /// When false, output is more compact but harder to read.
    /// Default: true
    /// </summary>
    public bool UseIndentation { get; init; } = true;

    /// <summary>
    /// Indent string (spaces or tabs).
    /// Default: "  " (2 spaces)
    /// </summary>
    public string IndentString { get; init; } = "  ";

    // === VERBOSITY ===

    /// <summary>
    /// Include type hints inline with values (e.g., Age = 30 &lt;int32&gt;).
    /// Useful for debugging but increases output size.
    /// Default: false (types only in @types section)
    /// </summary>
    public bool UseInlineTypeHints { get; init; } = false;

    /// <summary>
    /// Include property descriptions inline as comments.
    /// Useful for self-documenting output but increases size.
    /// Default: false (descriptions only in @types section)
    /// </summary>
    public bool UseInlineComments { get; init; } = false;

    /// <summary>
    /// Show array/collection count in output (e.g., Tags: &lt;string[]&gt; (count: 3)).
    /// Helps LLM understand collection size at a glance.
    /// Default: true
    /// </summary>
    public bool ShowCollectionCount { get; init; } = true;

    /// <summary>
    /// Use multi-line string format for strings longer than threshold.
    /// Strings use triple-quote syntax: """..."""
    /// Default: true
    /// </summary>
    public bool UseMultiLineStrings { get; init; } = true;

    /// <summary>
    /// Minimum string length to trigger multi-line format.
    /// Shorter strings remain inline with escaping.
    /// Default: 80 characters
    /// </summary>
    public int MultiLineStringThreshold { get; init; } = 80;

    /// <summary>
    /// Include enhanced property metadata (constraints, examples, purpose).
    /// Provides richer context for LLM understanding.
    /// Default: true
    /// </summary>
    public bool UseEnhancedMetadata { get; init; } = true;

    // === DATA CONTROL ===

    /// <summary>
    /// Omit properties with default/null values.
    /// Reduces output size significantly for sparse objects.
    /// Default: true
    /// </summary>
    public bool OmitDefaultValues { get; init; } = true;

    /// <summary>
    /// Write type names for root objects (e.g., Person { ... } vs just { ... }).
    /// Helps LLM understand object types in data section.
    /// Default: true
    /// </summary>
    public bool WriteTypeNames { get; init; } = true;

    /// <summary>
    /// Maximum string length before truncation in meta examples.
    /// Default: 50 characters
    /// </summary>
    public int MaxExampleStringLength { get; init; } = 50;

    // === PREDEFINED MODES ===

    /// <summary>
    /// Full mode: Meta + Data (first-time serialization).
    /// Use when LLM needs complete context about data structure and values.
    /// Returns a new instance each time to prevent shared state corruption.
    /// </summary>
    public static AcToonSerializerOptions Default => new()
    {
        Mode = ToonSerializationMode.Full,
        UseMeta = true,
        UseIndentation = true,
        OmitDefaultValues = true,
        WriteTypeNames = true
    };

    /// <summary>
    /// Meta-only mode: Only serialize type definitions and descriptions.
    /// Use this to send schema information once at conversation start.
    /// Subsequent serializations can use DataOnly mode to save tokens.
    /// Returns a new instance each time to prevent shared state corruption.
    /// </summary>
    public static AcToonSerializerOptions MetaOnly => new()
    {
        Mode = ToonSerializationMode.MetaOnly,
        UseMeta = true,
        UseIndentation = true,
        UseInlineComments = true
    };

    /// <summary>
    /// Data-only mode: Only serialize actual data values.
    /// Use this when schema was already sent via MetaOnly.
    /// Saves ~30-50% tokens in repeated serializations.
    /// Returns a new instance each time to prevent shared state corruption.
    /// </summary>
    public static AcToonSerializerOptions DataOnly => new()
    {
        Mode = ToonSerializationMode.DataOnly,
        UseMeta = false,
        UseIndentation = true,
        OmitDefaultValues = true,
        WriteTypeNames = true
    };

    /// <summary>
    /// Compact mode: Minimal output, no meta, no indentation.
    /// Maximum token efficiency but less readable.
    /// Returns a new instance each time to prevent shared state corruption.
    /// </summary>
    public static AcToonSerializerOptions Compact => new()
    {
        Mode = ToonSerializationMode.DataOnly,
        UseMeta = false,
        UseIndentation = true,
        OmitDefaultValues = true,
        WriteTypeNames = false,
        ReferenceHandling = ReferenceHandlingMode.None
    };

    /// <summary>
    /// Verbose mode: Everything included (for debugging/documentation).
    /// Use when you need maximum information and clarity.
    /// Returns a new instance each time to prevent shared state corruption.
    /// </summary>
    public static AcToonSerializerOptions Verbose => new()
    {
        Mode = ToonSerializationMode.Full,
        UseMeta = true,
        UseIndentation = true,
        UseInlineTypeHints = true,
        UseInlineComments = true,
        OmitDefaultValues = false,
        WriteTypeNames = true
    };

    /// <summary>
    /// Creates options with specified max depth.
    /// </summary>
    public static AcToonSerializerOptions WithMaxDepth(byte maxDepth) => new() { MaxDepth = maxDepth };

    /// <summary>
    /// Creates options without reference handling (faster, no circular reference support).
    /// </summary>
    public static AcToonSerializerOptions WithoutReferenceHandling() => new() { ReferenceHandling = ReferenceHandlingMode.None };
}
