using Microsoft.EntityFrameworkCore;
using MilitaryTrainingManagement.Models.Entities;

namespace MilitaryTrainingManagement.Data;

/// <summary>
/// 应用程序数据库上下文
/// </summary>
public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<OrganizationalUnit> OrganizationalUnits => Set<OrganizationalUnit>();
    public DbSet<UserAccount> UserAccounts => Set<UserAccount>();
    public DbSet<MaterialAllocation> MaterialAllocations => Set<MaterialAllocation>();
    public DbSet<AllocationDistribution> AllocationDistributions => Set<AllocationDistribution>();
    public DbSet<MaterialCategory> MaterialCategories => Set<MaterialCategory>();
    public DbSet<Personnel> Personnel => Set<Personnel>();
    public DbSet<PersonnelApprovalHistory> PersonnelApprovalHistories => Set<PersonnelApprovalHistory>();
    public DbSet<ApprovalRequest> ApprovalRequests => Set<ApprovalRequest>();
    public DbSet<AuditLog> AuditLogs => Set<AuditLog>();
    public DbSet<ConsumptionReport> ConsumptionReports => Set<ConsumptionReport>();
    public DbSet<ConsumptionReportChangeRequest> ConsumptionReportChangeRequests => Set<ConsumptionReportChangeRequest>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // OrganizationalUnit 配置
        modelBuilder.Entity<OrganizationalUnit>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Name).IsRequired().HasMaxLength(100);
            entity.HasOne(e => e.Parent)
                .WithMany(e => e.Children)
                .HasForeignKey(e => e.ParentId)
                .OnDelete(DeleteBehavior.Restrict);
        });

        // UserAccount 配置
        modelBuilder.Entity<UserAccount>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Username).IsRequired().HasMaxLength(50);
            entity.HasIndex(e => e.Username).IsUnique();
            entity.Property(e => e.PasswordHash).IsRequired();
            entity.Property(e => e.DisplayName).IsRequired().HasMaxLength(100);
            entity.HasOne(e => e.OrganizationalUnit)
                .WithMany(e => e.Accounts)
                .HasForeignKey(e => e.OrganizationalUnitId)
                .OnDelete(DeleteBehavior.Restrict);
        });

        // MaterialAllocation 配置
        modelBuilder.Entity<MaterialAllocation>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Category).IsRequired().HasMaxLength(100);
            entity.Property(e => e.MaterialName).IsRequired().HasMaxLength(200);
            entity.Property(e => e.Unit).IsRequired().HasMaxLength(50);
            entity.Property(e => e.TotalQuota).HasPrecision(18, 2);
            entity.HasOne(e => e.CreatedByUnit)
                .WithMany()
                .HasForeignKey(e => e.CreatedByUnitId)
                .OnDelete(DeleteBehavior.Restrict);
        });

        // MaterialCategory 配置
        modelBuilder.Entity<MaterialCategory>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Name).IsRequired().HasMaxLength(50);
            entity.HasIndex(e => e.Name).IsUnique();
            entity.Property(e => e.Description).HasMaxLength(200);
        });

        // AllocationDistribution 配置
        modelBuilder.Entity<AllocationDistribution>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.UnitQuota).HasPrecision(18, 2);
            entity.Property(e => e.ActualCompletion).HasPrecision(18, 2);
            entity.Ignore(e => e.CompletionRate);
            entity.HasOne(e => e.Allocation)
                .WithMany(e => e.Distributions)
                .HasForeignKey(e => e.AllocationId)
                .OnDelete(DeleteBehavior.Cascade);
            entity.HasOne(e => e.TargetUnit)
                .WithMany()
                .HasForeignKey(e => e.TargetUnitId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ReportedByUser)
                .WithMany()
                .HasForeignKey(e => e.ReportedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ApprovedByUser)
                .WithMany()
                .HasForeignKey(e => e.ApprovedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
        });

        // Personnel 配置
        modelBuilder.Entity<Personnel>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Name).IsRequired().HasMaxLength(50);
            entity.Property(e => e.Position).IsRequired().HasMaxLength(100);
            entity.Property(e => e.Rank).IsRequired().HasMaxLength(50);
            entity.Property(e => e.Gender).IsRequired().HasMaxLength(10);
            entity.Property(e => e.IdNumber).HasMaxLength(50);
            entity.Property(e => e.Height).HasPrecision(5, 2);
            entity.HasOne(e => e.SubmittedByUnit)
                .WithMany()
                .HasForeignKey(e => e.SubmittedByUnitId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ApprovedByUnit)
                .WithMany()
                .HasForeignKey(e => e.ApprovedByUnitId)
                .OnDelete(DeleteBehavior.NoAction);
        });

        // ApprovalRequest 配置
        modelBuilder.Entity<ApprovalRequest>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Reason).IsRequired().HasMaxLength(500);
            entity.Property(e => e.OriginalData).HasColumnType("nvarchar(max)");
            entity.Property(e => e.RequestedChanges).HasColumnType("nvarchar(max)");
            entity.HasOne(e => e.RequestedByUser)
                .WithMany()
                .HasForeignKey(e => e.RequestedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.RequestedByUnit)
                .WithMany()
                .HasForeignKey(e => e.RequestedByUnitId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ReviewedByUser)
                .WithMany()
                .HasForeignKey(e => e.ReviewedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
        });

        // AuditLog 配置
        modelBuilder.Entity<AuditLog>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.EntityType).IsRequired().HasMaxLength(100);
            entity.Property(e => e.Action).IsRequired().HasMaxLength(50);
            entity.Property(e => e.Description).HasMaxLength(500);
            entity.Property(e => e.OldValues).HasColumnType("nvarchar(max)");
            entity.Property(e => e.NewValues).HasColumnType("nvarchar(max)");
            entity.Property(e => e.ChangedFields).HasColumnType("nvarchar(max)");
            entity.Property(e => e.IpAddress).HasMaxLength(50);
            entity.Property(e => e.UserAgent).HasMaxLength(500);
            entity.Property(e => e.RequestPath).HasMaxLength(500);
            entity.Property(e => e.ErrorMessage).HasMaxLength(2000);
            entity.HasOne(e => e.User)
                .WithMany()
                .HasForeignKey(e => e.UserId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.OrganizationalUnit)
                .WithMany()
                .HasForeignKey(e => e.OrganizationalUnitId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasIndex(e => e.EntityType);
            entity.HasIndex(e => e.EntityId);
            entity.HasIndex(e => e.Action);
            entity.HasIndex(e => e.Timestamp);
            entity.HasIndex(e => e.UserId);
            entity.HasIndex(e => e.OrganizationalUnitId);
        });

        // PersonnelApprovalHistory 配置
        modelBuilder.Entity<PersonnelApprovalHistory>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.HasOne(e => e.Personnel)
                .WithMany()
                .HasForeignKey(e => e.PersonnelId)
                .OnDelete(DeleteBehavior.Cascade);
            entity.HasOne(e => e.ReviewedByUser)
                .WithMany()
                .HasForeignKey(e => e.ReviewedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ReviewedByUnit)
                .WithMany()
                .HasForeignKey(e => e.ReviewedByUnitId)
                .OnDelete(DeleteBehavior.NoAction);
        });

        // ConsumptionReport 配置
        modelBuilder.Entity<ConsumptionReport>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.ReportedAmount).HasPrecision(18, 2);
            entity.Property(e => e.CumulativeAmount).HasPrecision(18, 2);
            entity.Property(e => e.Remarks).HasMaxLength(500);
            entity.HasOne(e => e.AllocationDistribution)
                .WithMany()
                .HasForeignKey(e => e.AllocationDistributionId)
                .OnDelete(DeleteBehavior.Cascade);
            entity.HasOne(e => e.ReportedByUser)
                .WithMany()
                .HasForeignKey(e => e.ReportedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ReportedByUnit)
                .WithMany()
                .HasForeignKey(e => e.ReportedByUnitId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasIndex(e => e.AllocationDistributionId);
            entity.HasIndex(e => e.ReportedAt);
            entity.HasIndex(e => e.ReportedByUnitId);
        });

        // ConsumptionReportChangeRequest 配置
        modelBuilder.Entity<ConsumptionReportChangeRequest>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Reason).IsRequired().HasMaxLength(500);
            entity.Property(e => e.ProcessComments).HasMaxLength(500);
            entity.HasOne(e => e.ConsumptionReport)
                .WithMany()
                .HasForeignKey(e => e.ConsumptionReportId)
                .OnDelete(DeleteBehavior.Cascade);
            entity.HasOne(e => e.RequestedByUnit)
                .WithMany()
                .HasForeignKey(e => e.RequestedByUnitId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.RequestedByUser)
                .WithMany()
                .HasForeignKey(e => e.RequestedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ProcessedByUnit)
                .WithMany()
                .HasForeignKey(e => e.ProcessedByUnitId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasOne(e => e.ProcessedByUser)
                .WithMany()
                .HasForeignKey(e => e.ProcessedByUserId)
                .OnDelete(DeleteBehavior.NoAction);
            entity.HasIndex(e => e.ConsumptionReportId);
            entity.HasIndex(e => e.Status);
            entity.HasIndex(e => e.RequestedByUnitId);
        });
    }
}
