// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Extensions.Validation.GeneratorTests;
using VerifyXunit;
using Xunit;

namespace Microsoft.Extensions.Validation.GeneratorTests;

[UsesVerify]
public partial class ValidationsGeneratorTests : ValidationsGeneratorTestBase
{
    private const string GeneratedAttributeSource = """
        // <auto-generated/>
        namespace Microsoft.CodeAnalysis
        {
            [global::System.AttributeUsage(global::System.AttributeTargets.All, AllowMultiple = true, Inherited = false)]
            internal sealed class EmbeddedAttribute : global::System.Attribute
            {
            }
        }

        namespace Microsoft.Extensions.Validation.Embedded
        {
            [global::Microsoft.CodeAnalysis.EmbeddedAttribute]
            [global::System.AttributeUsage(global::System.AttributeTargets.Class)]
            internal sealed class ValidatableTypeAttribute : global::System.Attribute
            {
            }
        }
        """;

    [Fact]
    public async Task CanDiscoverGeneratedValidatableTypeAttribute()
    {
        var source = """

            namespace MyApp
            {
                using Microsoft.AspNetCore.Builder;
                using Microsoft.Extensions.DependencyInjection;
                using System.ComponentModel.DataAnnotations;
                using Microsoft.Extensions.Validation.Embedded;

                public class Program
                {
                    public static void Main(string[] args)
                    {
                        var builder = WebApplication.CreateBuilder(args);
                        builder.Services.AddValidation();
                        var app = builder.Build();
                        app.MapPost("/customers", (Customer customer) => "OK");
                        app.Run();
                    }
                }

                [ValidatableType]
                public class Customer
                {
                    [Required]
                    public string Name { get; set; } = "";

                    [EmailAddress]
                    public string Email { get; set; } = "";
                }
            }
            """;

        // Combine the generated attribute with the user's source
        var combinedSource = GeneratedAttributeSource + "\n" + source;

        await Verify(combinedSource, out var compilation);
    }

    [Fact]
    public async Task CanUseBothFrameworkAndGeneratedValidatableTypeAttributes()
    {
        var source = """
            namespace MyApp
            {
                using Microsoft.AspNetCore.Builder;
                using Microsoft.Extensions.DependencyInjection;
                using System.ComponentModel.DataAnnotations;
                using Microsoft.Extensions.Validation.Embedded;
            
                public class Program
                {
                    public static void Main(string[] args)
                    {
                        var builder = WebApplication.CreateBuilder(args);
                        builder.Services.AddValidation();
                        var app = builder.Build();
                        app.MapPost("/customers", (Customer customer) => "OK");
                        app.Run();
                    }
                }

                // Using framework attribute
                [Microsoft.Extensions.Validation.ValidatableType]
                public class Customer
                {
                    [Required]
                    public string Name { get; set; } = "";
            
                    [EmailAddress]
                    public string Email { get; set; } = "";
                }
            
                // Using generated attribute
                [ValidatableType]
                public class Product
                {
                    [Required]
                    public string ProductName { get; set; } = "";
            
                    [Range(0, double.MaxValue)]
                    public decimal Price { get; set; }
                }
            }
            """;

        // Combine the generated attribute with the user's source
        var combinedSource = GeneratedAttributeSource + "\n" + source;

        await Verify(combinedSource, out var compilation);
    }
}
