using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MiGu.DB.Domains.Dashboard;
using MiGu.DB.Domains.SimpleFields;
using MiGu.DB.Domains.Transport;
using MiGu.DB.Domains.Wms;
using MiGu.DB.Kernel.Entities;

namespace MiGu.DB.Domains.Wms;

public sealed class WarehouseConfiguration : IEntityTypeConfiguration<Warehouse>
{
    public void Configure(EntityTypeBuilder<Warehouse> b)
    {
        b.ToTable("wms_warehouses");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.Code).IsUnique();
    }
}

public sealed class WarehouseAreaConfiguration : IEntityTypeConfiguration<WarehouseArea>
{
    public void Configure(EntityTypeBuilder<WarehouseArea> b)
    {
        b.ToTable("wms_areas");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.Code).IsUnique();
        b.HasIndex(x => x.WarehouseId);
    }
}

public sealed class StorageConfiguration : IEntityTypeConfiguration<Storage>
{
    public void Configure(EntityTypeBuilder<Storage> b)
    {
        b.ToTable("wms_storages");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.Code).IsUnique();
        b.HasIndex(x => x.AreaId);
        b.HasIndex(x => x.Barcode);
    }
}

public sealed class ContainerConfiguration : IEntityTypeConfiguration<Container>
{
    public void Configure(EntityTypeBuilder<Container> b)
    {
        b.ToTable("wms_containers");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.Code).IsUnique();
    }
}

public sealed class MaterialTypeConfiguration : IEntityTypeConfiguration<MaterialType>
{
    public void Configure(EntityTypeBuilder<MaterialType> b)
    {
        b.ToTable("wms_material_types");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.Code).IsUnique();
    }
}

public sealed class MaterialConfiguration : IEntityTypeConfiguration<Material>
{
    public void Configure(EntityTypeBuilder<Material> b)
    {
        b.ToTable("wms_materials");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.Code).IsUnique();
        b.HasIndex(x => x.Barcode);
        b.HasIndex(x => new { x.LifecycleStatus, x.UpdatedAt });
        b.HasIndex(x => x.TypeCode);
    }
}

public sealed class ContainerLocationConfiguration : IEntityTypeConfiguration<ContainerLocation>
{
    public void Configure(EntityTypeBuilder<ContainerLocation> b)
    {
        b.ToTable("wms_container_locations");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.ContainerId).IsUnique();
        b.HasIndex(x => new { x.LocationType, x.LocationId });
        b.HasIndex(x => x.StorageId);
    }
}

public sealed class ContainerMaterialConfiguration : IEntityTypeConfiguration<ContainerMaterial>
{
    public void Configure(EntityTypeBuilder<ContainerMaterial> b)
    {
        b.ToTable("wms_container_materials");
        b.HasKey(x => x.Id);
        b.HasIndex(x => x.MaterialId).IsUnique();
        b.HasIndex(x => x.ContainerId);
        b.Property(x => x.Quantity).HasPrecision(18, 4);
    }
}

public sealed class StockEventConfiguration : IEntityTypeConfiguration<StockEvent>
{
    public void Configure(EntityTypeBuilder<StockEvent> b)
    {
        b.ToTable("wms_stock_events");
        b.HasKey(x => x.Id);
        b.Property(x => x.EventType).HasMaxLength(32);
        b.Property(x => x.MaterialCode).HasMaxLength(64);
        b.Property(x => x.MaterialName).HasMaxLength(128);
        b.Property(x => x.MaterialBarcode).HasMaxLength(128);
        b.Property(x => x.MaterialTypeCode).HasMaxLength(64);
        b.Property(x => x.ContainerCode).HasMaxLength(64);
        b.Property(x => x.ContainerName).HasMaxLength(128);
        b.Property(x => x.StorageCode).HasMaxLength(64);
        b.Property(x => x.StorageName).HasMaxLength(128);
        b.Property(x => x.AreaCode).HasMaxLength(64);
        b.Property(x => x.FromStorageCode).HasMaxLength(64);
        b.Property(x => x.FromStorageName).HasMaxLength(128);
        b.Property(x => x.ToStorageCode).HasMaxLength(64);
        b.Property(x => x.ToStorageName).HasMaxLength(128);
        b.Property(x => x.RefType).HasMaxLength(64);
        b.Property(x => x.RefCode).HasMaxLength(64);
        b.Property(x => x.Operator).HasMaxLength(128);
        b.Property(x => x.Reason).HasMaxLength(500);
        b.HasIndex(x => x.OperatedAt);
        b.HasIndex(x => x.EventType);
        b.HasIndex(x => x.MaterialId);
        b.HasIndex(x => x.ContainerId);
    }
}

public abstract class HistoryConfigurationBase<T> : IEntityTypeConfiguration<T> where T : HistoryEntity
{
    private readonly string _table;
    protected HistoryConfigurationBase(string table) => _table = table;

    public virtual void Configure(EntityTypeBuilder<T> b)
    {
        b.ToTable(_table);
        b.HasKey(x => x.Id);
        b.Property(x => x.EventType).HasMaxLength(64);
        b.Property(x => x.BeforeJson).HasColumnType("text");
        b.Property(x => x.AfterJson).HasColumnType("text");
        b.Property(x => x.Operator).HasMaxLength(128);
        b.Property(x => x.Source).HasMaxLength(32);
        b.Property(x => x.Reason).HasMaxLength(500);
        b.Property(x => x.Remark).HasMaxLength(1000);
        b.Property(x => x.Extend).HasColumnType("text");
        b.HasIndex(x => x.ContainerId);
        b.HasIndex(x => x.OperatedAt);
        b.HasIndex(x => x.EventType);
    }
}

public sealed class ContainerLocationHistoryConfiguration : HistoryConfigurationBase<ContainerLocationHistory>
{
    public ContainerLocationHistoryConfiguration() : base("wms_container_location_history") { }
}

public sealed class ContainerMaterialHistoryConfiguration : HistoryConfigurationBase<ContainerMaterialHistory>
{
    public ContainerMaterialHistoryConfiguration() : base("wms_container_material_history") { }

    public override void Configure(EntityTypeBuilder<ContainerMaterialHistory> b)
    {
        base.Configure(b);
        b.Property(x => x.QuantityDelta).HasPrecision(18, 4);
    }
}
