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

using GFramework.Core.SourceGenerators.Diagnostics;
using GFramework.SourceGenerators.Common.Constants;
using GFramework.SourceGenerators.Common.Generator;

namespace GFramework.Core.SourceGenerators.Bases;

/// <summary>
/// Priority 特性生成器，为标记了 [Priority] 的类自动生成 IPrioritized 接口实现
/// </summary>
[Generator]
public sealed class PriorityGenerator : MetadataAttributeClassGeneratorBase
{
    /// <summary>
    /// 获取特性的元数据名称
    /// </summary>
    protected override string AttributeMetadataName =>
        $"{PathContests.SourceGeneratorsAbstractionsPath}.Bases.PriorityAttribute";

    /// <summary>
    /// 获取特性的短名称（不包含后缀）
    /// </summary>
    protected override string AttributeShortNameWithoutSuffix => "Priority";

    /// <summary>
    /// 验证符号是否符合生成条件
    /// </summary>
    protected override bool ValidateSymbol(
        SourceProductionContext context,
        Compilation compilation,
        ClassDeclarationSyntax syntax,
        INamedTypeSymbol symbol,
        AttributeData attr)
    {
        // 1. 必须是 class
        if (symbol.TypeKind != TypeKind.Class)
        {
            context.ReportDiagnostic(Diagnostic.Create(
                PriorityDiagnostic.OnlyApplyToClass,
                syntax.Identifier.GetLocation(),
                symbol.ToDisplayString()));
            return false;
        }

        // 2. 不支持嵌套类
        if (symbol.ContainingType != null)
        {
            context.ReportDiagnostic(Diagnostic.Create(
                PriorityDiagnostic.NestedClassNotSupported,
                syntax.Identifier.GetLocation(),
                symbol.Name));
            return false;
        }

        // 3. 必须是 partial
        if (syntax.Modifiers.All(m => !m.IsKind(SyntaxKind.PartialKeyword)))
        {
            context.ReportDiagnostic(Diagnostic.Create(
                PriorityDiagnostic.MustBePartial,
                syntax.Identifier.GetLocation(),
                symbol.Name));
            return false;
        }

        // 4. 检查是否已手动实现 IPrioritized
        var iPrioritized = compilation.GetTypeByMetadataName(
            $"{PathContests.CoreAbstractionsNamespace}.Bases.IPrioritized");

        if (iPrioritized != null && symbol.AllInterfaces.Contains(iPrioritized, SymbolEqualityComparer.Default))
        {
            context.ReportDiagnostic(Diagnostic.Create(
                PriorityDiagnostic.AlreadyImplemented,
                syntax.Identifier.GetLocation(),
                symbol.Name));
            return false;
        }

        // 5. 验证特性参数
        if (attr.ConstructorArguments.Length == 0 ||
            attr.ConstructorArguments[0].Value is not int)
        {
            context.ReportDiagnostic(Diagnostic.Create(
                PriorityDiagnostic.InvalidValue,
                syntax.Identifier.GetLocation()));
            return false;
        }

        return true;
    }

    /// <summary>
    /// 生成源代码
    /// </summary>
    protected override string Generate(
        SourceProductionContext context,
        Compilation compilation,
        INamedTypeSymbol symbol,
        AttributeData attr)
    {
        var ns = symbol.ContainingNamespace.IsGlobalNamespace
            ? null
            : symbol.ContainingNamespace.ToDisplayString();

        var priorityValue = (int)attr.ConstructorArguments[0].Value!;

        var sb = new StringBuilder();
        sb.AppendLine("// <auto-generated/>");
        sb.AppendLine("#nullable enable");
        sb.AppendLine();

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

        // 生成泛型参数（如果有）
        var typeParameters = symbol.TypeParameters.Length > 0
            ? $"<{string.Join(", ", symbol.TypeParameters.Select(tp => tp.Name))}>"
            : string.Empty;

        sb.AppendLine("/// <summary>");
        sb.AppendLine("/// 为当前分部类型补充自动生成的优先级契约实现。");
        sb.AppendLine("/// </summary>");
        sb.AppendLine(
            $"partial class {symbol.Name}{typeParameters} : global::GFramework.Core.Abstractions.Bases.IPrioritized");
        sb.AppendLine("{");
        sb.AppendLine("    /// <summary>");
        sb.AppendLine($"    /// 获取优先级值: {priorityValue}");
        sb.AppendLine("    /// </summary>");
        sb.AppendLine($"    public int Priority => {priorityValue};");
        sb.AppendLine("}");

        return sb.ToString().TrimEnd();
    }

    /// <summary>
    /// 获取生成文件的提示名称
    /// </summary>
    protected override string GetHintName(INamedTypeSymbol symbol)
    {
        // 使用完整的元数据名称以避免冲突
        var metadataName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
            .Replace("global::", "")
            .Replace("<", "_")
            .Replace(">", "_")
            .Replace(",", "_")
            .Replace(" ", "")
            .Replace(".", "_");

        return $"{metadataName}.Priority.g.cs";
    }
}
