using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Haoliang.Data.Entities;
using Haoliang.Models.System;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;

namespace Haoliang.Data
{
    public class CNCBusinessDbContext : DbContext
    {
        public CNCBusinessDbContext(DbContextOptions<CNCBusinessDbContext> options) : base(options) { }

        // Device Management
        public DbSet<Models.Device.CNCDevice> Devices { get; set; }
        public DbSet<Models.Device.DeviceCurrentStatus> DeviceCurrentStatus { get; set; }
        public DbSet<Models.DataCollection.TagData> TagData { get; set; }

        // DeviceStatus as string property (since it's an enum)
        public string DeviceStatus { get; set; } = null!;

        // Template Management
        public DbSet<Models.Template.CNCBrandTemplate> CNCTemplates { get; set; }
        public DbSet<Models.Template.TagMapping> TagMappings { get; set; }

        // Production Management
        public DbSet<Models.Production.ProductionRecord> ProductionRecords { get; set; }
        public DbSet<Models.Production.ProgramProductionSummary> ProgramProductionSummary { get; set; }
        public DbSet<Models.Production.ProductionSummary> ProductionSummaries { get; set; }

        // User Management
        public DbSet<Models.User.User> Users { get; set; }
        public DbSet<Models.User.Role> Roles { get; set; }
        public DbSet<Models.User.Employee> Employees { get; set; }
        public DbSet<Models.User.UserPermission> UserPermissions { get; set; }
        public DbSet<Models.User.RolePermission> RolePermissions { get; set; }
        public DbSet<Models.User.UserSession> UserSessions { get; set; }
        public DbSet<Models.User.PasswordReset> PasswordResets { get; set; }

        // System Management
        public DbSet<Models.System.Alarm> Alarms { get; set; }
        public DbSet<Models.System.AlarmRule> AlarmRules { get; set; }
        public DbSet<Models.System.AlarmNotification> AlarmNotifications { get; set; }
        public DbSet<Models.System.SystemConfig> SystemConfigs { get; set; }
        public DbSet<Models.System.LogEntry> LogEntries { get; set; }
        public DbSet<Models.System.StatisticRule> StatisticRules { get; set; }
        public DbSet<Models.System.StatisticResult> StatisticResults { get; set; }

        // Data Collection
        public DbSet<Models.DataCollection.CollectionTask> CollectionTasks { get; set; }
        public DbSet<Models.DataCollection.CollectionResult> CollectionResults { get; set; }
        public DbSet<Models.DataCollection.CollectionLog> CollectionLogs { get; set; }
        public DbSet<Models.DataCollection.CollectionConfig> CollectionConfigs { get; set; }

        // Scheduled Tasks
        public DbSet<Models.System.ScheduledTask> ScheduledTasks { get; set; }
        public DbSet<Models.System.TaskExecutionResult> TaskExecutionResults { get; set; }

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

            // Configure relationships
            ConfigureDeviceRelationships(modelBuilder);
            ConfigureUserRelationships(modelBuilder);
            ConfigureAlarmRelationships(modelBuilder);
            ConfigureCollectionRelationships(modelBuilder);
            ConfigureProductionRelationships(modelBuilder);
            ConfigureTemplateRelationships(modelBuilder);

            // Configure indexes
            ConfigureIndexes(modelBuilder);

            // Configure constraints
            ConfigureConstraints(modelBuilder);

            // Configure data conversions
            ConfigureDataConversions(modelBuilder);
        }

        private void ConfigureDeviceRelationships(ModelBuilder modelBuilder)
        {
        }

        private void ConfigureUserRelationships(ModelBuilder modelBuilder)
        {
        }

        private void ConfigureAlarmRelationships(ModelBuilder modelBuilder)
        {
        }

        private void ConfigureCollectionRelationships(ModelBuilder modelBuilder)
        {
        }

        private void ConfigureProductionRelationships(ModelBuilder modelBuilder)
        {
        }

        private void ConfigureTemplateRelationships(ModelBuilder modelBuilder)
        {
        }

        private void ConfigureIndexes(ModelBuilder modelBuilder)
        {
            // Device indexes
            modelBuilder.Entity<Models.Device.CNCDevice>()
                .HasIndex(d => d.DeviceCode)
                .IsUnique();

            modelBuilder.Entity<Models.Device.CNCDevice>()
                .HasIndex(d => d.IPAddress);

            modelBuilder.Entity<Models.Device.CNCDevice>()
                .HasIndex(d => d.IsOnline);

            modelBuilder.Entity<Models.Device.CNCDevice>()
                .HasIndex(d => d.IsAvailable);

            // User indexes
            modelBuilder.Entity<Models.User.User>()
                .HasIndex(u => u.Username)
                .IsUnique();

            modelBuilder.Entity<Models.User.User>()
                .HasIndex(u => u.Email)
                .IsUnique();

            modelBuilder.Entity<Models.User.User>()
                .HasIndex(u => u.IsActive);

            // Alarm indexes
            modelBuilder.Entity<Models.System.Alarm>()
                .HasIndex(a => a.IsResolved);

            // Collection indexes
            modelBuilder.Entity<Models.DataCollection.CollectionResult>()
                .HasIndex(cr => cr.DeviceId);

            modelBuilder.Entity<Models.DataCollection.CollectionResult>()
                .HasIndex(cr => cr.CollectionTime);

            modelBuilder.Entity<Models.DataCollection.CollectionResult>()
                .HasIndex(cr => cr.IsSuccess);

            // Production indexes
            modelBuilder.Entity<Models.Production.ProductionRecord>()
                .HasIndex(pr => pr.DeviceId);

            modelBuilder.Entity<Models.Production.ProductionRecord>()
                .HasIndex(pr => pr.ProductionDate);

            modelBuilder.Entity<Models.Production.ProductionRecord>()
                .HasIndex(pr => pr.IsCompleted);

            // Template indexes
            modelBuilder.Entity<Models.Template.CNCBrandTemplate>()
                .HasIndex(t => t.BrandName);

            // System config indexes
            modelBuilder.Entity<Models.System.SystemConfig>()
                .HasIndex(sc => sc.ConfigKey)
                .IsUnique();

            modelBuilder.Entity<Models.System.SystemConfig>()
                .HasIndex(sc => sc.Category);

            modelBuilder.Entity<Models.System.SystemConfig>()
                .HasIndex(sc => sc.IsActive);
        }

        private void ConfigureConstraints(ModelBuilder modelBuilder)
        {
            // Device constraints
            modelBuilder.Entity<Models.Device.CNCDevice>()
                .Property(d => d.DeviceCode)
                .IsRequired()
                .HasMaxLength(50);

            modelBuilder.Entity<Models.Device.CNCDevice>()
                .Property(d => d.DeviceName)
                .IsRequired()
                .HasMaxLength(100);

            modelBuilder.Entity<Models.Device.CNCDevice>()
                .Property(d => d.IPAddress)
                .IsRequired()
                .HasMaxLength(15);

            modelBuilder.Entity<Models.Device.CNCDevice>()
                .Property(d => d.HttpUrl)
                .IsRequired()
                .HasMaxLength(255);

            modelBuilder.Entity<Models.Device.CNCDevice>()
                .Property(d => d.CollectionInterval)
                .IsRequired();

            // User constraints
            modelBuilder.Entity<Models.User.User>()
                .Property(u => u.Username)
                .IsRequired()
                .HasMaxLength(50);

            modelBuilder.Entity<Models.User.User>()
                .Property(u => u.Email)
                .IsRequired()
                .HasMaxLength(100);

            modelBuilder.Entity<Models.User.User>()
                .Property(u => u.PasswordHash)
                .IsRequired()
                .HasMaxLength(255);

            // Alarm constraints
            modelBuilder.Entity<Models.System.Alarm>()
                .Property(a => a.AlarmType)
                .IsRequired()
                .HasMaxLength(50);

            // System config constraints
            modelBuilder.Entity<Models.System.SystemConfig>()
                .Property(sc => sc.ConfigKey)
                .IsRequired()
                .HasMaxLength(100);

            modelBuilder.Entity<Models.System.SystemConfig>()
                .Property(sc => sc.ConfigValue)
                .IsRequired();

            modelBuilder.Entity<Models.System.SystemConfig>()
                .Property(sc => sc.Category)
                .IsRequired()
                .HasMaxLength(50);
        }

        private void ConfigureDataConversions(ModelBuilder modelBuilder)
        {
            // Configure decimal properties with appropriate precision
            modelBuilder.Entity<Models.Production.ProductionSummary>()
                .Property(ps => ps.QualityRate)
                .HasColumnType("decimal(5,2)");

            modelBuilder.Entity<Models.System.SystemConfig>()
                .Property(sc => sc.ConfigValue)
                .HasColumnType("text");

            modelBuilder.Entity<Models.DataCollection.CollectionLog>()
                .Property(cl => cl.LogData)
                .HasColumnType("text");

            modelBuilder.Entity<Models.DataCollection.CollectionResult>()
                .Property(cr => cr.RawJson)
                .HasColumnType("json");

            modelBuilder.Entity<Models.DataCollection.CollectionResult>()
                .Property(cr => cr.ParsedData)
                .HasColumnType("text");
        }

        public static void ConfigureDatabaseServices(IServiceCollection services, IConfiguration configuration)
        {
            var connectionString = configuration.GetConnectionString("CNCBusinessDb");
            
            services.AddDbContext<CNCBusinessDbContext>(options =>
            {
                options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), 
                    mysqlOptions =>
                    {
                        mysqlOptions.EnableRetryOnFailure(
                            maxRetryCount: 3,
                            maxRetryDelay: TimeSpan.FromSeconds(30),
                            errorNumbersToAdd: null);
                    });
                
                // Enable lazy loading for development
                if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
                {
                    options.EnableSensitiveDataLogging();
                    options.EnableDetailedErrors();
                }
            });
        }
    }
}