using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using SolutionErp.Domain.PurchaseEvaluations;

namespace SolutionErp.Infrastructure.Persistence.Configurations;

public class PurchaseEvaluationConfiguration : IEntityTypeConfiguration<PurchaseEvaluation>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluation> b)
    {
        b.ToTable("PurchaseEvaluations");
        b.HasKey(x => x.Id);

        b.Property(x => x.MaPhieu).HasMaxLength(100);
        b.Property(x => x.Type).HasConversion<int>();
        b.Property(x => x.Phase).HasConversion<int>();
        b.Property(x => x.RejectedFromPhase).HasConversion<int?>();
        b.Property(x => x.TenGoiThau).HasMaxLength(500).IsRequired();
        b.Property(x => x.DiaDiem).HasMaxLength(500);
        b.Property(x => x.MoTa).HasMaxLength(2000);
        b.Property(x => x.PaymentTerms).HasColumnType("nvarchar(max)");
        b.Property(x => x.BudgetManualName).HasMaxLength(200);
        b.Property(x => x.BudgetManualAmount).HasPrecision(18, 2);

        b.HasIndex(x => x.MaPhieu).IsUnique().HasFilter("[MaPhieu] IS NOT NULL");
        b.HasIndex(x => new { x.Phase, x.IsDeleted });
        b.HasIndex(x => x.ProjectId);
        b.HasIndex(x => x.SlaDeadline);
        b.HasIndex(x => x.WorkflowDefinitionId);
        b.HasIndex(x => x.ContractId);
        b.HasIndex(x => x.BudgetId);

        b.HasMany(x => x.Suppliers).WithOne(s => s.PurchaseEvaluation).HasForeignKey(s => s.PurchaseEvaluationId).OnDelete(DeleteBehavior.Cascade);
        b.HasMany(x => x.Details).WithOne(d => d.PurchaseEvaluation).HasForeignKey(d => d.PurchaseEvaluationId).OnDelete(DeleteBehavior.Cascade);
        b.HasMany(x => x.Approvals).WithOne(a => a.PurchaseEvaluation).HasForeignKey(a => a.PurchaseEvaluationId).OnDelete(DeleteBehavior.Cascade);
        b.HasMany(x => x.Changelogs).WithOne(c => c.PurchaseEvaluation).HasForeignKey(c => c.PurchaseEvaluationId).OnDelete(DeleteBehavior.Cascade);
        b.HasMany(x => x.Attachments).WithOne(a => a.PurchaseEvaluation).HasForeignKey(a => a.PurchaseEvaluationId).OnDelete(DeleteBehavior.Cascade);
        b.HasMany(x => x.DepartmentOpinions).WithOne(o => o.PurchaseEvaluation).HasForeignKey(o => o.PurchaseEvaluationId).OnDelete(DeleteBehavior.Cascade);
        // Quotes không FK trực tiếp tới PurchaseEvaluation (đi qua Detail) —
        // nhưng collection navigation có nên cần config riêng bên dưới.

        b.HasQueryFilter(x => !x.IsDeleted);
    }
}

public class PurchaseEvaluationSupplierConfiguration : IEntityTypeConfiguration<PurchaseEvaluationSupplier>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationSupplier> b)
    {
        b.ToTable("PurchaseEvaluationSuppliers");
        b.HasKey(x => x.Id);

        b.Property(x => x.DisplayName).HasMaxLength(200);
        b.Property(x => x.ContactName).HasMaxLength(200);
        b.Property(x => x.ContactEmail).HasMaxLength(200);
        b.Property(x => x.ContactPhone).HasMaxLength(50);
        b.Property(x => x.PaymentTermText).HasMaxLength(200);
        b.Property(x => x.Note).HasMaxLength(500);

        b.HasIndex(x => new { x.PurchaseEvaluationId, x.SupplierId }).IsUnique();
        b.HasIndex(x => x.SupplierId);
    }
}

public class PurchaseEvaluationDetailConfiguration : IEntityTypeConfiguration<PurchaseEvaluationDetail>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationDetail> b)
    {
        b.ToTable("PurchaseEvaluationDetails");
        b.HasKey(x => x.Id);

        b.Property(x => x.GroupCode).HasMaxLength(50).IsRequired();
        b.Property(x => x.GroupName).HasMaxLength(200).IsRequired();
        b.Property(x => x.ItemCode).HasMaxLength(100);
        b.Property(x => x.NoiDung).HasMaxLength(500).IsRequired();
        b.Property(x => x.DonViTinh).HasMaxLength(50);
        b.Property(x => x.GhiChu).HasMaxLength(1000);
        b.Property(x => x.KhoiLuongNganSach).HasPrecision(18, 4);
        b.Property(x => x.KhoiLuongThiCong).HasPrecision(18, 4);
        b.Property(x => x.DonGiaNganSach).HasPrecision(18, 2);
        b.Property(x => x.ThanhTienNganSach).HasPrecision(18, 2);

        b.HasIndex(x => new { x.PurchaseEvaluationId, x.Order });

        b.HasMany(x => x.Quotes).WithOne(q => q.Detail).HasForeignKey(q => q.PurchaseEvaluationDetailId).OnDelete(DeleteBehavior.Cascade);
    }
}

public class PurchaseEvaluationQuoteConfiguration : IEntityTypeConfiguration<PurchaseEvaluationQuote>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationQuote> b)
    {
        b.ToTable("PurchaseEvaluationQuotes");
        b.HasKey(x => x.Id);

        b.Property(x => x.BgVat).HasPrecision(18, 2);
        b.Property(x => x.ChuaVat).HasPrecision(18, 2);
        b.Property(x => x.ThanhTien).HasPrecision(18, 2);
        b.Property(x => x.Note).HasMaxLength(500);

        b.HasIndex(x => new { x.PurchaseEvaluationDetailId, x.PurchaseEvaluationSupplierId }).IsUnique();

        // Quote → Supplier (restrict — không xóa Supplier-row khỏi phiếu nếu còn quote)
        b.HasOne(x => x.Supplier)
            .WithMany()
            .HasForeignKey(x => x.PurchaseEvaluationSupplierId)
            .OnDelete(DeleteBehavior.Restrict);
    }
}

public class PurchaseEvaluationApprovalConfiguration : IEntityTypeConfiguration<PurchaseEvaluationApproval>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationApproval> b)
    {
        b.ToTable("PurchaseEvaluationApprovals");
        b.HasKey(x => x.Id);

        b.Property(x => x.FromPhase).HasConversion<int>();
        b.Property(x => x.ToPhase).HasConversion<int>();
        b.Property(x => x.Decision).HasConversion<int>();
        b.Property(x => x.Comment).HasMaxLength(1000);

        b.HasIndex(x => new { x.PurchaseEvaluationId, x.ApprovedAt });
    }
}

public class PurchaseEvaluationChangelogConfiguration : IEntityTypeConfiguration<PurchaseEvaluationChangelog>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationChangelog> b)
    {
        b.ToTable("PurchaseEvaluationChangelogs");
        b.HasKey(x => x.Id);

        b.Property(x => x.EntityType).HasConversion<int>();
        b.Property(x => x.Action).HasConversion<int>();
        b.Property(x => x.PhaseAtChange).HasConversion<int>();
        b.Property(x => x.UserName).HasMaxLength(200);
        b.Property(x => x.Summary).HasMaxLength(500);
        b.Property(x => x.ContextNote).HasMaxLength(2000);
        b.Property(x => x.FieldChangesJson).HasColumnType("nvarchar(max)");

        b.HasIndex(x => new { x.PurchaseEvaluationId, x.CreatedAt });
        b.HasIndex(x => new { x.PurchaseEvaluationId, x.EntityType });
    }
}

public class PurchaseEvaluationAttachmentConfiguration : IEntityTypeConfiguration<PurchaseEvaluationAttachment>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationAttachment> b)
    {
        b.ToTable("PurchaseEvaluationAttachments");
        b.HasKey(x => x.Id);

        b.Property(x => x.FileName).HasMaxLength(255).IsRequired();
        b.Property(x => x.StoragePath).HasMaxLength(500).IsRequired();
        b.Property(x => x.ContentType).HasMaxLength(100).IsRequired();
        b.Property(x => x.Purpose).HasConversion<int>();
        b.Property(x => x.Note).HasMaxLength(500);

        b.HasIndex(x => x.PurchaseEvaluationId);
        b.HasIndex(x => x.PurchaseEvaluationSupplierId);
    }
}

public class PurchaseEvaluationWorkflowDefinitionConfiguration : IEntityTypeConfiguration<PurchaseEvaluationWorkflowDefinition>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationWorkflowDefinition> e)
    {
        e.ToTable("PurchaseEvaluationWorkflowDefinitions");
        e.Property(x => x.Code).HasMaxLength(100).IsRequired();
        e.Property(x => x.Name).HasMaxLength(200).IsRequired();
        e.Property(x => x.Description).HasMaxLength(1000);
        e.Property(x => x.EvaluationType).HasConversion<int>();

        e.HasIndex(x => new { x.Code, x.Version }).IsUnique();
        e.HasIndex(x => new { x.EvaluationType, x.IsActive });
    }
}

public class PurchaseEvaluationWorkflowStepConfiguration : IEntityTypeConfiguration<PurchaseEvaluationWorkflowStep>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationWorkflowStep> e)
    {
        e.ToTable("PurchaseEvaluationWorkflowSteps");
        e.Property(x => x.Name).HasMaxLength(200).IsRequired();
        e.Property(x => x.Phase).HasConversion<int>();

        e.HasOne(x => x.Definition)
            .WithMany(d => d.Steps)
            .HasForeignKey(x => x.PurchaseEvaluationWorkflowDefinitionId)
            .OnDelete(DeleteBehavior.Cascade);

        e.HasIndex(x => new { x.PurchaseEvaluationWorkflowDefinitionId, x.Order });
    }
}

public class PurchaseEvaluationWorkflowStepApproverConfiguration : IEntityTypeConfiguration<PurchaseEvaluationWorkflowStepApprover>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationWorkflowStepApprover> e)
    {
        e.ToTable("PurchaseEvaluationWorkflowStepApprovers");
        e.Property(x => x.Kind).HasConversion<int>();
        e.Property(x => x.AssignmentValue).HasMaxLength(100).IsRequired();

        e.HasOne(x => x.Step)
            .WithMany(s => s.Approvers)
            .HasForeignKey(x => x.PurchaseEvaluationWorkflowStepId)
            .OnDelete(DeleteBehavior.Cascade);
    }
}

// Mirror ContractCodeSequenceConfiguration — Prefix là PK, atomic UPDATE qua
// SERIALIZABLE transaction trong PurchaseEvaluationCodeGenerator.
public class PurchaseEvaluationCodeSequenceConfiguration
    : IEntityTypeConfiguration<PurchaseEvaluationCodeSequence>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationCodeSequence> b)
    {
        b.ToTable("PurchaseEvaluationCodeSequences");
        b.HasKey(x => x.Prefix);
        b.Property(x => x.Prefix).HasMaxLength(100);
    }
}

public class PurchaseEvaluationDepartmentOpinionConfiguration
    : IEntityTypeConfiguration<PurchaseEvaluationDepartmentOpinion>
{
    public void Configure(EntityTypeBuilder<PurchaseEvaluationDepartmentOpinion> b)
    {
        b.ToTable("PurchaseEvaluationDepartmentOpinions");
        b.HasKey(x => x.Id);

        b.Property(x => x.Kind).HasConversion<int>();
        b.Property(x => x.Opinion).HasMaxLength(2000);
        b.Property(x => x.UserName).HasMaxLength(200);

        // Each PE × Kind unique — max 1 ý kiến per phòng ban per phiếu.
        // UPDATE in-place khi user đổi ý → audit qua Changelog.
        b.HasIndex(x => new { x.PurchaseEvaluationId, x.Kind }).IsUnique();
    }
}
