// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0

using GFramework.Core.SourceGenerators.Abstractions.Logging;
using GFramework.SourceGenerators.Common.Constants;
using GFramework.SourceGenerators.Common.Extensions;
using GFramework.SourceGenerators.Common.Generator;

namespace GFramework.Core.SourceGenerators.Logging;

/// <summary>
///     日志生成器，用于为标记了LogAttribute的类自动生成日志字段
/// </summary>
[Generator]
public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
{
    /// <summary>
    ///     获取属性元数据的完整名称，用于标识日志属性的完全限定名
    /// </summary>
    protected override Type AttributeType => typeof(LogAttribute);

    /// <summary>
    ///     用于语法快速筛选
    /// </summary>
    protected override string AttributeShortNameWithoutSuffix => "Log";


    /// <summary>
    ///     对类进行额外语义校验（可选）
    /// </summary>
    protected override bool ValidateSymbol(
        SourceProductionContext context,
        Compilation compilation,
        ClassDeclarationSyntax syntax,
        INamedTypeSymbol symbol,
        AttributeData attr)
    {
        // 可以加自定义规则，比如确保类是 public 或实现某接口
        return true;
    }

    /// <summary>
    ///     生成源代码
    /// </summary>
    /// <param name="context">源生产上下文</param>
    /// <param name="compilation">编译对象</param>
    /// <param name="symbol">命名类型符号</param>
    /// <param name="attr">属性数据</param>
    /// <returns>生成的源代码字符串</returns>
    protected override string Generate(
        SourceProductionContext context,
        Compilation compilation,
        INamedTypeSymbol symbol,
        AttributeData attr)
    {
        var ns = symbol.GetNamespace();
        var className = symbol.GetFullClassName();
        var typeKind = symbol.ResolveTypeKind();
        var generics = symbol.ResolveGenerics();

        var logName = attr.GetFirstCtorString(className);
        var fieldName = attr.GetNamedArgument("FieldName", "_log");
        var access = attr.GetNamedArgument("AccessModifier", "private");
        var isStatic = attr.GetNamedArgument("IsStatic", true);
        var staticKeyword = isStatic ? "static " : "";

        var sb = new StringBuilder()
            .AppendLine("// <auto-generated />")
            .AppendLine($"using {PathContests.CoreAbstractionsNamespace}.Logging;")
            .AppendLine($"using {PathContests.CoreNamespace}.Logging;");

        if (ns is not null)
            sb.AppendLine()
                .AppendLine($"namespace {ns};");

        sb.AppendLine()
            .AppendLine("/// <summary>")
            .AppendLine("/// 为当前分部类型提供自动生成的日志字段。")
            .AppendLine("/// </summary>")
            .AppendLine($"partial {typeKind} {className}{generics.Parameters}");

        foreach (var c in generics.Constraints)
            sb.AppendLine($"    {c}");

        sb.AppendLine("{")
            .AppendLine("    /// <summary>")
            .AppendLine("    /// 自动生成的日志字段。")
            .AppendLine("    /// </summary>")
            .AppendLine(
                $"    {access} {staticKeyword}readonly ILogger {fieldName} = " +
                $"LoggerFactoryResolver.Provider.CreateLogger(\"{logName}\");")
            .AppendLine("}");

        return sb.ToString();
    }


    /// <summary>
    ///     可以自定义生成文件名
    /// </summary>
    protected override string GetHintName(INamedTypeSymbol symbol)
    {
        return $"{symbol.Name}.Logger.g.cs";
    }
}
