<#@ template hostSpecific="true" #>
<#@ assembly name="Microsoft.EntityFrameworkCore" #>
<#@ assembly name="Microsoft.EntityFrameworkCore.Design" #>
<#@ assembly name="Microsoft.EntityFrameworkCore.Relational" #>
<#@ assembly name="Microsoft.Extensions.DependencyInjection.Abstractions" #>
<#@ parameter name="EntityType" type="Microsoft.EntityFrameworkCore.Metadata.IEntityType" #>
<#@ parameter name="Options" type="Microsoft.EntityFrameworkCore.Scaffolding.ModelCodeGenerationOptions" #>
<#@ parameter name="NamespaceHint" type="System.String" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.ComponentModel.DataAnnotations" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="Microsoft.EntityFrameworkCore" #>
<#@ import namespace="Microsoft.EntityFrameworkCore.Design" #>
<#@ import namespace="Microsoft.Extensions.DependencyInjection" #>
<#
    if (EntityType.IsSimpleManyToManyJoinEntityType())
    {
        // Don't scaffold these
        return "";
    }

    var services = (IServiceProvider)Host;
    var annotationCodeGenerator = services.GetRequiredService<IAnnotationCodeGenerator>();
    var code = services.GetRequiredService<ICSharpHelper>();

    var usings = new List<string>
    {
    };

    if (Options.UseDataAnnotations)
    {
        usings.Add("IRaCIS.Core.Domain.Models");
    }

    if (!string.IsNullOrEmpty(NamespaceHint))
    {
#>
namespace <#= NamespaceHint #>;

<#
    }

    if (!string.IsNullOrEmpty(EntityType.GetComment()))
    {
#>
[Comment("<#= code.XmlComment(EntityType.GetComment().Replace("\\", "|").Trim()) #>")]
<#
    }

    if (Options.UseDataAnnotations)
    {
        foreach (var dataAnnotation in EntityType.GetDataAnnotations(annotationCodeGenerator))
        {
#>
<#= code.Fragment(dataAnnotation) #>
<#
        }
    }
#>
public partial class <#= EntityType.Name #>: BaseFullAuditEntity
{
<#
    var firstProperty = true;
    var excludedColumns = new[] { "CreateUserId", "Id", "UpdateUserId", "CreateTime", "UpdateTime", "DeleteUserId", "IsDeleted", "DeletedTime" };
    foreach (var property in EntityType.GetProperties().OrderBy(p => p.GetColumnOrder() ?? -1).OrderBy(t=>t.Name))
    {
      if (!excludedColumns.Contains(property.Name))
      {
        if (!firstProperty)
        {
            WriteLine("");
        }

        if (!string.IsNullOrEmpty(property.GetComment()))
        {
#>
    [Comment("<#= code.XmlComment(property.GetComment().Replace("\\", "|").Trim()) #>")]
<#
        }
 

        if (Options.UseDataAnnotations)
        {
            // 检查属性是否为字符串类型，并根据MaxLength来决定是否生成[StringLength]注解
            if (property.ClrType == typeof(string))
            {
                var maxLength = property.GetMaxLength();
                
                if (maxLength.HasValue && maxLength != 200) // 仅当长度不为200时生成[StringLength]
                {
#>
    [StringLength(<#= maxLength.Value #>)]
<#                   
                }
                else if(maxLength.HasValue && maxLength == 200){}
                else
                {
#>

    [MaxLength] 
<#
                }
            }
            if (property.ClrType == typeof(decimal) || property.ClrType == typeof(decimal?))
            {
                var typeName = property.GetColumnType()??""; // 获取数据库类型名称
                // 匹配 decimal, numeric, 或者 number 格式
                var match = System.Text.RegularExpressions.Regex.Match(typeName, @"(decimal|numeric|number)\((\d+),(\d+)\)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                if (match.Success)
                {
                    var precision = match.Groups[2].Value;
                    var scale = match.Groups[3].Value;
#>
    [DecimalPrecision(<#= precision #>, <#= scale #>)]
<#
                }

                else
                {
#>
    [DecimalPrecision(18, 2)] // 默认值
<#
                }
            }

           var dataAnnotations = property.GetDataAnnotations(annotationCodeGenerator)
                    .Where(a => !(a.Type == typeof(RequiredAttribute) && Options.UseNullableReferenceTypes && !property.ClrType.IsValueType)
            && a.Type != typeof(StringLengthAttribute) // 排除 StringLengthAttribute        
             );
            
            foreach (var dataAnnotation in dataAnnotations)
            {
               //过滤    [Column(TypeName = "decimal(18,1)")]  这种设置TypeName的  直接过滤&& a.Type != typeof(ColumnAttribute)  会报错，很奇怪
              if(dataAnnotation.Arguments?.Count==0)
              {
                 continue;
              }

              if(dataAnnotation.Arguments?[0]== property.GetColumnName() && property.GetColumnName() !=property.Name )
              {
                continue;
              }
         
#>
    <#= code.Fragment(dataAnnotation) #>
<#
            }
        }

        usings.AddRange(code.GetRequiredUsings(property.ClrType));

        var needsNullable = Options.UseNullableReferenceTypes && property.IsNullable && !property.ClrType.IsValueType;
        var needsInitializer = Options.UseNullableReferenceTypes && !property.IsNullable && !property.ClrType.IsValueType;
#>
    public <#= code.Reference(property.ClrType) #><#= needsNullable ? "?" : "" #> <#= property.GetColumnName() #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>
<#
        firstProperty = false;
     }
    }

    foreach (var navigation in EntityType.GetNavigations())
    {
        WriteLine("");

        if (Options.UseDataAnnotations)
        {
            foreach (var dataAnnotation in navigation.GetDataAnnotations(annotationCodeGenerator))
            {
#>
    <#= code.Fragment(dataAnnotation) #>
<#
            }
        }

        var targetType = navigation.TargetEntityType.Name;
        if (navigation.IsCollection)
        {
#>
    public virtual ICollection<<#= targetType #>> <#= navigation.Name #> { get; set; } = new List<<#= targetType #>>();
<#
        }
        else
        {
            var needsNullable = Options.UseNullableReferenceTypes && !(navigation.ForeignKey.IsRequired && navigation.IsOnDependent);
            var needsInitializer = Options.UseNullableReferenceTypes && navigation.ForeignKey.IsRequired && navigation.IsOnDependent;
#>
    public virtual <#= targetType #><#= needsNullable ? "?" : "" #> <#= navigation.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>
<#
        }
    }

    foreach (var skipNavigation in EntityType.GetSkipNavigations())
    {
        WriteLine("");

        if (Options.UseDataAnnotations)
        {
            foreach (var dataAnnotation in skipNavigation.GetDataAnnotations(annotationCodeGenerator))
            {
#>
    <#= code.Fragment(dataAnnotation) #>
<#
            }
        }
#>
    public virtual ICollection<<#= skipNavigation.TargetEntityType.Name #>> <#= skipNavigation.Name #> { get; set; } = new List<<#= skipNavigation.TargetEntityType.Name #>>();
<#
    }
#>
}
<#
    var previousOutput = GenerationEnvironment;
    GenerationEnvironment = new StringBuilder();

    foreach (var ns in usings.Distinct().OrderBy(x => x, new NamespaceComparer()))
    {
#>
using <#= ns #>;
<#
    }

    WriteLine("");

    GenerationEnvironment.Append(previousOutput);
#>
