using ERPCore.Domain.Entities;
using ERPCore.Domain.Enums;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace ERPCore.Infra.Persistence.Configurations;

public sealed class SalesInvoiceConfiguration : IEntityTypeConfiguration<SalesInvoice>
{
    public void Configure(EntityTypeBuilder<SalesInvoice> builder)
    {
        builder.ToTable("sales_invoices");
        builder.HasKey(x => x.SalesInvoiceId);

        builder.Property(x => x.InvoiceNo).IsRequired().HasMaxLength(50);
        builder.HasIndex(x => x.InvoiceNo).IsUnique();

        builder.Property(x => x.InvoiceDate).IsRequired();

        builder.HasOne(x => x.Customer)
            .WithMany()
            .HasForeignKey(x => x.CustomerId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.Property(x => x.CustomerSnapshotName).IsRequired().HasMaxLength(200);
        builder.Property(x => x.CustomerSnapshotTaxNo).HasMaxLength(50);

        builder.HasOne(x => x.Warehouse)
            .WithMany()
            .HasForeignKey(x => x.WarehouseId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.Property(x => x.InvoiceType)
            .HasConversion<string>().HasMaxLength(20).IsRequired()
            .HasDefaultValue(SalesInvoiceType.B2C);

        builder.Property(x => x.Status)
            .HasConversion<string>().HasMaxLength(20).IsRequired()
            .HasDefaultValue(SalesInvoiceStatus.Draft);

        foreach (var p in new[] { nameof(SalesInvoice.Subtotal), nameof(SalesInvoice.DiscountTotal), nameof(SalesInvoice.TaxTotal), nameof(SalesInvoice.GrandTotal), nameof(SalesInvoice.RoundOff), nameof(SalesInvoice.NetPayable), nameof(SalesInvoice.PaidAmount), nameof(SalesInvoice.BalanceAmount) })
            builder.Property<decimal>(p).HasPrecision(18, 4);
        builder.Property(x => x.GlJournalNo).HasMaxLength(30);

        builder.Property(x => x.CreatedAt).IsRequired();
        builder.Property(x => x.RowVersion).IsRowVersion();

        builder.HasIndex(x => x.Status);
        builder.HasIndex(x => x.InvoiceDate);

        builder.HasMany(x => x.Lines)
            .WithOne(x => x.SalesInvoice)
            .HasForeignKey(x => x.SalesInvoiceId)
            .OnDelete(DeleteBehavior.Cascade);
    }
}

public sealed class SalesInvoicePaymentConfiguration : IEntityTypeConfiguration<SalesInvoicePayment>
{
    public void Configure(EntityTypeBuilder<SalesInvoicePayment> builder)
    {
        builder.ToTable("sales_invoice_payments");
        builder.HasKey(p => p.SalesInvoicePaymentId);

        builder.Property(p => p.Amount).HasPrecision(18, 4);
        builder.Property(p => p.PaymentDate).IsRequired();
        builder.Property(p => p.BankAccountName).IsRequired().HasMaxLength(200);
        builder.Property(p => p.Reference).HasMaxLength(100);
        builder.Property(p => p.GlJournalNo).HasMaxLength(30);
        builder.Property(p => p.CreatedAt).IsRequired();

        builder.HasOne(p => p.SalesInvoice).WithMany(x => x.Payments).HasForeignKey(p => p.SalesInvoiceId).OnDelete(DeleteBehavior.Restrict);
        builder.HasOne(p => p.Creator).WithMany().HasForeignKey(p => p.CreatedBy).OnDelete(DeleteBehavior.Restrict);

        builder.HasIndex(p => p.SalesInvoiceId);
    }
}

public sealed class SalesInvoiceLineConfiguration : IEntityTypeConfiguration<SalesInvoiceLine>
{
    public void Configure(EntityTypeBuilder<SalesInvoiceLine> builder)
    {
        builder.ToTable("sales_invoice_lines");
        builder.HasKey(x => x.SalesInvoiceLineId);

        builder.HasOne(x => x.Item)
            .WithMany()
            .HasForeignKey(x => x.ItemId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.Property(x => x.Description).IsRequired().HasMaxLength(200);

        builder.Property(x => x.Qty).HasPrecision(18, 4);
        builder.Property(x => x.FreeQty).HasPrecision(18, 4);
        builder.Property(x => x.UnitPrice).HasPrecision(18, 4);
        builder.Property(x => x.BaseCost).HasPrecision(18, 4);
        builder.Property(x => x.DiscountPct).HasPrecision(9, 4);
        builder.Property(x => x.DiscountAmount).HasPrecision(18, 4);
        builder.Property(x => x.NetUnitPrice).HasPrecision(18, 4);
        builder.Property(x => x.LineTotal).HasPrecision(18, 4);
        builder.Property(x => x.TaxPct).HasPrecision(9, 4);
        builder.Property(x => x.TaxAmount).HasPrecision(18, 4);

        builder.HasOne(x => x.Warehouse)
            .WithMany()
            .HasForeignKey(x => x.WarehouseId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.Property(x => x.PriceSource).HasMaxLength(50);
        builder.Property(x => x.RowVersion).IsRowVersion();
    }
}
