using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;  // json
using ContactManagementSystem.Models;
using System;
using System.IO;

namespace ContactManagementSystem.Data
{
    /// <summary>
    /// Application database context for Contact Management System
    /// Manages database connection and entity configurations
    /// Uses appsettings.json for connection string configuration
    /// </summary>
    public class ApplicationDbContext : DbContext
    {
        #region DbSet Properties

        /// <summary>
        /// DbSet for Contact entities
        /// Represents the Contacts table in the database
        /// </summary>
        public DbSet<Contact> Contacts { get; set; }

        // DAY 4 CONTACTNOTE DBSET
        public DbSet<ContactNote> ContactNotes { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Default constructor - Uses OnConfiguring with appsettings.json
        /// Used for: Migrations, simple applications, console apps
        /// </summary>
        public ApplicationDbContext()
        {
        }

        /// <summary>
        /// Constructor with options - Supports Dependency Injection
        /// Used for: ASP.NET Core, testability, advanced scenarios
        /// </summary>
        /// <param name="options">DbContext options</param>
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        #endregion

        // <summary>
        /// Configures the database connection using appsettings.json
        /// Only used when DbContextOptions not provided via constructor
        /// </summary>
        /// <param name="optionsBuilder">Options builder</param>
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // Only configure if not already configured (allows DI to override)
            if (!optionsBuilder.IsConfigured)
            {
                // Build configuration from appsettings.json
                var configuration = new ConfigurationBuilder() // Microsoft.Extensions.json
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .Build();

                // Get connection string from appsettings.json
                var connectionString = configuration.GetConnectionString("DefaultConnection");

                // Validate connection string exists
                if (string.IsNullOrEmpty(connectionString))
                {
                    throw new InvalidOperationException(
                        "Connection string 'DefaultConnection' not found in appsettings.json. " +
                        "Please ensure appsettings.json exists and contains ConnectionStrings section.");
                }

                // Use Pomelo MySQL provider (recommended for MySQL with EF Core)
                optionsBuilder.UseMySql(
                    connectionString,
                    ServerVersion.AutoDetect(connectionString)
                );

                // Optional: Enable sensitive data logging for development
                // WARNING: Only use in development - exposes sensitive data in logs
#if DEBUG
                optionsBuilder.EnableSensitiveDataLogging();
               // optionsBuilder.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
#endif
            }
        }

        /// <summary>
        /// Configures entity models and relationships
        /// Called when model is being created
        /// </summary>
        /// <param name="modelBuilder">Model builder</param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Contact>(entity =>
            {
                // Table name
                entity.ToTable("Contacts");

                // Primary key
                entity.HasKey(c => c.Id);

                // Property configurations
                entity.Property(c => c.Id)
                    .ValueGeneratedOnAdd(); // Auto-increment

                entity.Property(c => c.FirstName)
                    .IsRequired()
                    .HasMaxLength(50)
                    .HasColumnType("varchar(50)");

                entity.Property(c => c.LastName)
                    .IsRequired()
                    .HasMaxLength(50)
                    .HasColumnType("varchar(50)");

                entity.Property(c => c.Email)
                    .IsRequired()
                    .HasMaxLength(100)
                    .HasColumnType("varchar(100)");

                entity.Property(c => c.PhoneNumber)
                    .IsRequired()
                    .HasMaxLength(20)
                    .HasColumnType("varchar(20)");

                entity.Property(c => c.Address)
                    .HasMaxLength(200)
                    .HasColumnType("varchar(200)");

                entity.Property(c => c.Company)
                    .HasMaxLength(100)
                    .HasColumnType("varchar(100)");

                entity.Property(c => c.JobTitle)
                    .HasMaxLength(100)
                    .HasColumnType("varchar(100)");

                entity.Property(c => c.NotesText) // DAY 4 UPDATE
                    .HasColumnName("Notes") // DAY 4 ADD
                    .HasColumnType("text");

                entity.Property(c => c.IsFavorite)
                    .IsRequired()
                    .HasDefaultValue(false);

                entity.Property(c => c.DateCreated)
                    .IsRequired()
                    .HasDefaultValueSql("CURRENT_TIMESTAMP");

                entity.Property(c => c.DateModified)
                    .IsRequired()
                    .HasDefaultValueSql("CURRENT_TIMESTAMP");

                // Indexes for performance Search terms
                entity.HasIndex(c => c.Email)
                    .IsUnique()
                    .HasDatabaseName("IX_Contacts_Email");

                entity.HasIndex(c => c.LastName)
                    .HasDatabaseName("IX_Contacts_LastName");

                entity.HasIndex(c => new { c.LastName, c.FirstName })
                    .HasDatabaseName("IX_Contacts_LastName_FirstName");

                entity.HasIndex(c => c.Company)
                    .HasDatabaseName("IX_Contacts_Company");

                entity.HasIndex(c => c.IsFavorite)
                    .HasDatabaseName("IX_Contacts_IsFavorite");
            });

            // DAY4 CONTACTNOTE
            // ContactNote Configuration
            modelBuilder.Entity<ContactNote>(entity =>
            {
                entity.ToTable("ContactNotes"); // CONTACT_NOTES
                entity.HasKey(n => n.Id); // Primary Key

                entity.Property(n => n.Content).IsRequired();
                entity.Property(n => n.DateCreated).IsRequired();

                // Foreign Key Relationship  n = notes tables  and c contact table
                entity.HasOne(n => n.Contact)           // ContactNote has one Contact
                      .WithMany(c => c.Notes)           // Contact has many Notes
                      .HasForeignKey(n => n.ContactId)  // Foreign key is ContactId
                      .OnDelete(DeleteBehavior.Cascade); // Delete notes when contact deleted
            });
        }

        /// <summary>
        /// Applies any pending migrations
        /// </summary>
        public void ApplyMigrations()
        {
            Database.Migrate();
        }

    }
}