using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.RegularExpressions;

namespace ContactManagementSystem.Models
{
    /// <summary>
    /// Contact class representing a person with contact information
    /// Updated for Entity Framework Core integration
    /// Demonstrates: Data Annotations, EF Core entity configuration
    /// </summary>
    [Table("Contacts")] // Explicit table name (optional)
    public class Contact : Person
    {
        #region Private Fields
        private string _email;
        private string _phoneNumber;
        #endregion

        #region Primary Key

        /// <summary>
        /// Primary key for database
        /// EF Core will auto-increment this
        /// </summary>
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        #endregion

        #region Public Properties with Validation

        /// <summary>
        /// Email address - must be in valid format
        /// </summary>
        [Required(ErrorMessage = "Email is required")]
        [EmailAddress(ErrorMessage = "Invalid email format")]
        [MaxLength(255)]
        [Column("Email", TypeName = "varchar(255)")]
        public string Email
        {
            get => _email;
            set
            {
                if (string.IsNullOrWhiteSpace(value))
                {
                    throw new ArgumentException("Email cannot be empty.", nameof(Email));
                }

                // Basic email validation
                if (!IsValidEmail(value))
                {
                    throw new ArgumentException("Email must be in valid format (e.g., user@example.com).", nameof(Email));
                }

                _email = value.Trim().ToLower();
            }
        }

        /// <summary>
        /// Phone number - must be in valid format
        /// </summary>
        [Required(ErrorMessage = "Phone number is required")]
        [Phone(ErrorMessage = "Invalid phone number format")]
        [MaxLength(20)]
        [Column("PhoneNumber", TypeName = "varchar(20)")]
        public string PhoneNumber
        {
            get => _phoneNumber;
            set
            {
                if (string.IsNullOrWhiteSpace(value))
                {
                    throw new ArgumentException("Phone number cannot be empty.", nameof(PhoneNumber));
                }

                // Basic phone validation
                if (!IsValidPhoneNumber(value))
                {
                    throw new ArgumentException("Phone number must contain at least 10 digits.", nameof(PhoneNumber));
                }

                _phoneNumber = value.Trim();
            }
        }

        /// <summary>
        /// Address of the contact (optional)
        /// </summary>
        [MaxLength(500)]
        [Column("Address", TypeName = "varchar(500)")]
        public string? Address { get; set; }

        /// <summary>
        /// Company name (optional)
        /// </summary>
        [MaxLength(200)]
        [Column("Company", TypeName = "varchar(200)")]
        public string? Company { get; set; }

        /// <summary>
        /// Job title (optional)
        /// </summary>
        [MaxLength(100)]
        [Column("JobTitle", TypeName = "varchar(100)")]
        public string? JobTitle { get; set; }

        /// <summary>
        /// Notes about the contact (optional)
        /// </summary>
        [MaxLength(1000)]
        [Column("Notes", TypeName = "text")]
        public string? Notes { get; set; }

        /// <summary>
        /// Indicates if contact is marked as favorite
        /// </summary>
        [Required]
        [Column("IsFavorite")]
        public bool IsFavorite { get; set; }

        /// <summary>
        /// Date when the contact was created
        /// </summary>
        [Required]
        [Column("DateCreated")]
        public DateTime DateCreated { get; set; }

        /// <summary>
        /// Date when the contact was last modified
        /// </summary>
        [Required]
        [Column("DateModified")]
        public DateTime DateModified { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Default constructor (required for EF Core)
        /// </summary>
        public Contact() : base() // class Contact : Person
        {
            DateCreated = DateTime.Now;
            DateModified = DateTime.Now;
            IsFavorite = false;
        }

        /// <summary>
        /// Constructor with required parameters
        /// </summary>
        /// <param name="firstName">First name</param>
        /// <param name="lastName">Last name</param>
        /// <param name="email">Email address</param>
        /// <param name="phoneNumber">Phone number</param>
        public Contact(string firstName, string lastName, string email, string phoneNumber)
            : base(firstName, lastName)
        {
            Email = email;
            PhoneNumber = phoneNumber;
            DateCreated = DateTime.Now;
            DateModified = DateTime.Now;
            IsFavorite = false;
        }

        #endregion

        #region Validation Methods (Private Helpers)

        /// <summary>
        /// Validates email format using regex
        /// </summary>
        /// <param name="email">Email to validate</param>
        /// <returns>True if valid, false otherwise</returns>
        private bool IsValidEmail(string email)
        {
            if (string.IsNullOrWhiteSpace(email))
                return false;

            try
            {
                // Basic email regex pattern
                string pattern = @"^[^@\s]+@[^@\s]+\.[^@\s]+$";
                return Regex.IsMatch(email, pattern, RegexOptions.IgnoreCase);
            }
            catch (RegexMatchTimeoutException)
            {
                return false;
            }
        }

        /// <summary>
        /// Validates phone number format
        /// </summary>
        /// <param name="phoneNumber">Phone number to validate</param>
        /// <returns>True if valid, false otherwise</returns>
        private bool IsValidPhoneNumber(string phoneNumber)
        {
            if (string.IsNullOrWhiteSpace(phoneNumber))
                return false;

            // Remove all non-digit characters
            string digitsOnly = Regex.Replace(phoneNumber, @"\D", "");

            // Must have at least 10 digits
            return digitsOnly.Length >= 10;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Validates all required fields of the contact
        /// Throws exception if validation fails
        /// </summary>
        public void Validate()
        {
            if (string.IsNullOrWhiteSpace(FirstName))
                throw new InvalidOperationException("First name is required");

            if (string.IsNullOrWhiteSpace(LastName))
                throw new InvalidOperationException("Last name is required");

            if (string.IsNullOrWhiteSpace(Email))
                throw new InvalidOperationException("Email is required");

            if (string.IsNullOrWhiteSpace(PhoneNumber))
                throw new InvalidOperationException("Phone number is required");
        }

        /// <summary>
        /// Gets formatted contact information
        /// </summary>
        /// <returns>Formatted string with all contact details</returns>
        public string GetContactInfo()
        {
            return $"{GetFullName()}\n" +
                   $"Email: {Email}\n" +
                   $"Phone: {PhoneNumber}\n" +
                   $"Address: {(string.IsNullOrEmpty(Address) ? "N/A" : Address)}\n" +
                   $"Company: {(string.IsNullOrEmpty(Company) ? "N/A" : Company)}\n" +
                   $"Job Title: {(string.IsNullOrEmpty(JobTitle) ? "N/A" : JobTitle)}\n" +
                   $"Favorite: {(IsFavorite ? "Yes" : "No")}";
        }

        /// <summary>
        /// Updates the DateModified timestamp
        /// Should be called whenever the contact is modified
        /// </summary>
        public void UpdateModifiedDate()
        {
            DateModified = DateTime.Now;
        }

        /// <summary>
        /// Checks if the contact matches a search term
        /// Searches in FirstName, LastName, Email, Phone, Company
        /// </summary>
        /// <param name="searchTerm">Term to search for</param>
        /// <returns>True if match found, false otherwise</returns>
        public bool MatchesSearchTerm(string searchTerm)
        {
            if (string.IsNullOrWhiteSpace(searchTerm))
                return false;

            searchTerm = searchTerm.ToLower();

            return FirstName.ToLower().Contains(searchTerm) ||
                   LastName.ToLower().Contains(searchTerm) ||
                   Email.ToLower().Contains(searchTerm) ||
                   PhoneNumber.Contains(searchTerm) ||
                   (Company?.ToLower().Contains(searchTerm) ?? false);  // Use null-conditional operator
        }
        #endregion

        #region Method Overrides (Polymorphism)

        /// <summary>
        /// Overrides base GetFullName to include email
        /// </summary>
        /// <returns>Full name with email</returns>
        public override string GetFullName()
        {
            return $"{base.GetFullName()} ({Email})";
        }

        /// <summary>
        /// Overrides base DisplayInfo to show complete contact information
        /// Demonstrates polymorphism
        /// </summary>
        public override void DisplayInfo()
        {
            Console.WriteLine("==================== CONTACT INFO ====================");
            Console.WriteLine($"ID:          {Id}");
            Console.WriteLine($"Name:        {FirstName} {LastName}");
            Console.WriteLine($"Email:       {Email}");
            Console.WriteLine($"Phone:       {PhoneNumber}");
            Console.WriteLine($"Address:     {(string.IsNullOrEmpty(Address) ? "N/A" : Address)}");
            Console.WriteLine($"Company:     {(string.IsNullOrEmpty(Company) ? "N/A" : Company)}");
            Console.WriteLine($"Job Title:   {(string.IsNullOrEmpty(JobTitle) ? "N/A" : JobTitle)}");
            Console.WriteLine($"Favorite:    {(IsFavorite ? "★ Yes" : "No")}");
            Console.WriteLine($"Created:     {DateCreated:yyyy-MM-dd HH:mm:ss}");
            Console.WriteLine($"Modified:    {DateModified:yyyy-MM-dd HH:mm:ss}");
            Console.WriteLine("======================================================");
        }

        /// <summary>
        /// Provides a string representation of the contact
        /// </summary>
        /// <returns>Contact summary string</returns>
        public override string ToString()
        {
            return $"{Id}. {FirstName} {LastName} - {Email} - {PhoneNumber}";
        }

        #endregion
    }
}

/* INSTRUCTOR NOTES:
 * 
 * Data Annotations:
 * - [Key]: Marks property as primary key
 * - [Required]: Property cannot be null
 * - [MaxLength]: Sets maximum string length
 * - [Column]: Specifies database column name and type
 * - [Table]: Specifies database table name
 * - [DatabaseGenerated]: Specifies how values are generated
 * 
 * EF Core Conventions:
 * - Property named "Id" or "ClassNameId" is automatically the primary key
 * - String properties map to nvarchar(max) by default
 * - DateTime properties map to datetime2 in SQL Server, datetime in MySQL
 * - Navigation properties create foreign key relationships
 * 
 * Best Practices:
 * - Always have a parameterless constructor for EF Core
 * - Use Data Annotations OR Fluent API, not both (Fluent API takes precedence)
 * - Keep validation logic in setters
 * - Use UpdateModifiedDate() before SaveChanges()
 */
