/*
 * File: ShadowedRealms.Data/Repositories/Repository.cs
 * Created: 2025-10-19
 * Last Modified: 2025-10-22
 * Description: Base repository implementation providing kingdom-scoped data access operations using Entity Framework Core.
 *              Implements complete IRepository interface with automatic kingdom filtering, transaction safety, and performance optimization.
 * Last Edit Notes: Fixed all compilation errors to match IRepository<T,K> interface signatures exactly with CancellationToken support
 */

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;
using ShadowedRealms.Core.Interfaces;
using ShadowedRealms.Core.Interfaces.Repositories;
using ShadowedRealms.Core.Models;
using ShadowedRealms.Data.Contexts;
using System.Linq.Expressions;

namespace ShadowedRealms.Data.Repositories
{
    /// <summary>
    /// Base repository implementation providing kingdom-scoped data access operations.
    /// All derived repositories inherit kingdom security, transaction safety, and performance optimization.
    /// </summary>
    /// <typeparam name="T">Entity type that implements IKingdomScoped</typeparam>
    /// <typeparam name="K">Primary key type</typeparam>
    public class Repository<T, K> : IRepository<T, K> where T : class, IKingdomScoped
    {
        protected readonly GameDbContext _context;
        protected readonly DbSet<T> _dbSet;
        protected readonly ILogger<Repository<T, K>> _logger;

        public Repository(GameDbContext context, ILogger<Repository<T, K>> logger)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _dbSet = _context.Set<T>();
        }

        #region Kingdom-Scoped Query Operations

        /// <summary>
        /// Gets entity by ID with kingdom validation
        /// </summary>
        public virtual async Task<T?> GetByIdAsync(K id, int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting {EntityType} with ID {Id} for Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);

                var entity = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .FirstOrDefaultAsync(e => EF.Property<K>(e, "Id").Equals(id), cancellationToken);

                if (entity == null)
                {
                    _logger.LogDebug("Entity {EntityType} with ID {Id} not found in Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);
                }

                return entity;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get {EntityType} with ID {Id} operation cancelled", typeof(T).Name, id);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting {EntityType} with ID {Id} for Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);
                throw new InvalidOperationException($"Failed to retrieve {typeof(T).Name} with ID {id}", ex);
            }
        }

        /// <summary>
        /// Gets entity by ID with kingdom validation and custom includes
        /// </summary>
        public virtual async Task<T?> GetByIdWithIncludesAsync(K id, int kingdomId, CancellationToken cancellationToken = default,
            params Expression<Func<T, object>>[] includeProperties)
        {
            try
            {
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting {EntityType} with ID {Id} for Kingdom {KingdomId} with {IncludeCount} includes",
                    typeof(T).Name, id, kingdomId, includeProperties?.Length ?? 0);

                var query = _dbSet.Where(e => e.KingdomId == kingdomId);

                // Apply includes
                if (includeProperties != null)
                {
                    foreach (var include in includeProperties)
                    {
                        query = query.Include(include);
                    }
                }

                var entity = await query.FirstOrDefaultAsync(e => EF.Property<K>(e, "Id").Equals(id), cancellationToken);

                if (entity == null)
                {
                    _logger.LogDebug("Entity {EntityType} with ID {Id} not found in Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);
                }

                return entity;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get {EntityType} with ID {Id} and includes operation cancelled", typeof(T).Name, id);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting {EntityType} with ID {Id} and includes for Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);
                throw new InvalidOperationException($"Failed to retrieve {typeof(T).Name} with ID {id} and includes", ex);
            }
        }

        /// <summary>
        /// Gets all entities in kingdom
        /// </summary>
        public virtual async Task<IEnumerable<T>> GetAllAsync(int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting all {EntityType} for Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var entities = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .ToListAsync(cancellationToken);

                _logger.LogDebug("Retrieved {Count} {EntityType} entities for Kingdom {KingdomId}",
                    entities.Count, typeof(T).Name, kingdomId);

                return entities;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get all {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting all {EntityType} for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to retrieve {typeof(T).Name} entities", ex);
            }
        }

        /// <summary>
        /// Gets entities matching predicate with kingdom scoping
        /// </summary>
        public virtual async Task<IEnumerable<T>> GetWhereAsync(Expression<Func<T, bool>> predicate, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (predicate == null)
                    throw new ArgumentNullException(nameof(predicate));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting {EntityType} entities matching predicate for Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var entities = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .Where(predicate)
                    .ToListAsync(cancellationToken);

                _logger.LogDebug("Found {Count} {EntityType} entities matching predicate for Kingdom {KingdomId}",
                    entities.Count, typeof(T).Name, kingdomId);

                return entities;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get where {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting {EntityType} entities where predicate for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to get {typeof(T).Name} entities matching predicate", ex);
            }
        }

        /// <summary>
        /// Gets entities matching predicate with kingdom scoping and includes
        /// </summary>
        public virtual async Task<IEnumerable<T>> GetWhereWithIncludesAsync(Expression<Func<T, bool>> predicate, int kingdomId,
            CancellationToken cancellationToken = default, params Expression<Func<T, object>>[] includeProperties)
        {
            try
            {
                if (predicate == null)
                    throw new ArgumentNullException(nameof(predicate));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting {EntityType} entities with {IncludeCount} includes matching predicate for Kingdom {KingdomId}",
                    typeof(T).Name, includeProperties?.Length ?? 0, kingdomId);

                var query = _dbSet.Where(e => e.KingdomId == kingdomId);

                // Apply includes
                if (includeProperties != null)
                {
                    foreach (var include in includeProperties)
                    {
                        query = query.Include(include);
                    }
                }

                var entities = await query.Where(predicate).ToListAsync(cancellationToken);

                _logger.LogDebug("Found {Count} {EntityType} entities with includes matching predicate for Kingdom {KingdomId}",
                    entities.Count, typeof(T).Name, kingdomId);

                return entities;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get where with includes {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting {EntityType} entities with includes where predicate for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to get {typeof(T).Name} entities with includes matching predicate", ex);
            }
        }

        /// <summary>
        /// Gets first entity matching predicate or null
        /// </summary>
        public virtual async Task<T?> GetFirstOrDefaultAsync(Expression<Func<T, bool>> predicate, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (predicate == null)
                    throw new ArgumentNullException(nameof(predicate));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting first {EntityType} matching predicate for Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var entity = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .FirstOrDefaultAsync(predicate, cancellationToken);

                if (entity == null)
                {
                    _logger.LogDebug("No {EntityType} found matching predicate for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                }

                return entity;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get first or default {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting first {EntityType} for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to get first {typeof(T).Name}", ex);
            }
        }

        #endregion

        #region Paginated Query Operations

        /// <summary>
        /// Gets paginated results with kingdom scoping
        /// </summary>
        public virtual async Task<(IEnumerable<T> Items, int TotalCount, int PageCount)> GetPagedAsync(int pageNumber, int pageSize,
            int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (pageNumber < 1)
                    throw new ArgumentException("Page number must be 1 or greater", nameof(pageNumber));
                if (pageSize < 1)
                    throw new ArgumentException("Page size must be 1 or greater", nameof(pageSize));
                if (pageSize > 1000)
                    throw new ArgumentException("Page size cannot exceed 1000", nameof(pageSize));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting paged {EntityType} for Kingdom {KingdomId}: Page {Page}, Size {PageSize}",
                    typeof(T).Name, kingdomId, pageNumber, pageSize);

                var query = _dbSet.Where(e => e.KingdomId == kingdomId);

                var totalCount = await query.CountAsync(cancellationToken);
                var pageCount = (int)Math.Ceiling((double)totalCount / pageSize);

                var items = await query
                    .Skip((pageNumber - 1) * pageSize)
                    .Take(pageSize)
                    .ToListAsync(cancellationToken);

                _logger.LogDebug("Retrieved {ItemCount} of {TotalCount} {EntityType} entities for Kingdom {KingdomId}",
                    items.Count, totalCount, typeof(T).Name, kingdomId);

                return (items, totalCount, pageCount);
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get paged {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting paged {EntityType} for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to get paged {typeof(T).Name} results", ex);
            }
        }

        /// <summary>
        /// Gets paginated filtered results with kingdom scoping
        /// </summary>
        public virtual async Task<(IEnumerable<T> Items, int TotalCount, int PageCount)> GetPagedWhereAsync(
            Expression<Func<T, bool>> predicate, int pageNumber, int pageSize, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (predicate == null)
                    throw new ArgumentNullException(nameof(predicate));
                if (pageNumber < 1)
                    throw new ArgumentException("Page number must be 1 or greater", nameof(pageNumber));
                if (pageSize < 1)
                    throw new ArgumentException("Page size must be 1 or greater", nameof(pageSize));
                if (pageSize > 1000)
                    throw new ArgumentException("Page size cannot exceed 1000", nameof(pageSize));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Getting paged filtered {EntityType} for Kingdom {KingdomId}: Page {Page}, Size {PageSize}",
                    typeof(T).Name, kingdomId, pageNumber, pageSize);

                var query = _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .Where(predicate);

                var totalCount = await query.CountAsync(cancellationToken);
                var pageCount = (int)Math.Ceiling((double)totalCount / pageSize);

                var items = await query
                    .Skip((pageNumber - 1) * pageSize)
                    .Take(pageSize)
                    .ToListAsync(cancellationToken);

                _logger.LogDebug("Retrieved {ItemCount} of {TotalCount} filtered {EntityType} entities for Kingdom {KingdomId}",
                    items.Count, totalCount, typeof(T).Name, kingdomId);

                return (items, totalCount, pageCount);
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Get paged where {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting paged filtered {EntityType} for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to get paged filtered {typeof(T).Name} results", ex);
            }
        }

        #endregion

        #region Count and Existence Operations

        /// <summary>
        /// Counts all entities in kingdom
        /// </summary>
        public virtual async Task<int> CountAsync(int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Counting {EntityType} entities for Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var count = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .CountAsync(cancellationToken);

                _logger.LogDebug("Count of {EntityType} for Kingdom {KingdomId}: {Count}", typeof(T).Name, kingdomId, count);

                return count;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Count {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error counting {EntityType} entities for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to count {typeof(T).Name} entities", ex);
            }
        }

        /// <summary>
        /// Counts entities matching predicate in kingdom
        /// </summary>
        public virtual async Task<int> CountWhereAsync(Expression<Func<T, bool>> predicate, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (predicate == null)
                    throw new ArgumentNullException(nameof(predicate));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Counting {EntityType} entities matching predicate for Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var count = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .CountAsync(predicate, cancellationToken);

                _logger.LogDebug("Count of {EntityType} matching predicate for Kingdom {KingdomId}: {Count}", typeof(T).Name, kingdomId, count);

                return count;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Count where {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error counting {EntityType} entities matching predicate for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to count {typeof(T).Name} entities matching predicate", ex);
            }
        }

        /// <summary>
        /// Checks if any entity exists in kingdom
        /// </summary>
        public virtual async Task<bool> AnyAsync(int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Checking if any {EntityType} exists for Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var result = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .AnyAsync(cancellationToken);

                _logger.LogDebug("Any {EntityType} exists for Kingdom {KingdomId}: {Result}", typeof(T).Name, kingdomId, result);

                return result;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Any {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error checking if any {EntityType} exists for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to check existence of {typeof(T).Name}", ex);
            }
        }

        /// <summary>
        /// Checks if any entity matches predicate in kingdom
        /// </summary>
        public virtual async Task<bool> AnyAsync(Expression<Func<T, bool>> predicate, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (predicate == null)
                    throw new ArgumentNullException(nameof(predicate));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Checking if any {EntityType} matching predicate exists for Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var result = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .AnyAsync(predicate, cancellationToken);

                _logger.LogDebug("Any {EntityType} matching predicate exists for Kingdom {KingdomId}: {Result}", typeof(T).Name, kingdomId, result);

                return result;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Any where {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error checking if any {EntityType} matching predicate exists for Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to check existence of {typeof(T).Name} matching predicate", ex);
            }
        }

        #endregion

        #region Modification Operations

        /// <summary>
        /// Adds new entity with kingdom validation
        /// </summary>
        public virtual async Task<T> AddAsync(T entity, int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException(nameof(entity));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Adding new {EntityType} to Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                // Validate kingdom ID matches
                if (entity.KingdomId != kingdomId)
                {
                    throw new ArgumentException($"Entity kingdom ID ({entity.KingdomId}) must match provided kingdom ID ({kingdomId})");
                }

                var addedEntity = await _dbSet.AddAsync(entity, cancellationToken);

                _logger.LogDebug("Successfully added {EntityType} to Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                return addedEntity.Entity;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Add {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error adding {EntityType} to Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to add {typeof(T).Name}", ex);
            }
        }

        /// <summary>
        /// Adds multiple entities with kingdom validation
        /// </summary>
        public virtual async Task<IEnumerable<T>> AddRangeAsync(IEnumerable<T> entities, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (entities == null)
                    throw new ArgumentNullException(nameof(entities));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                var entitiesList = entities.ToList();
                if (!entitiesList.Any())
                    return new List<T>();

                _logger.LogDebug("Adding {Count} {EntityType} entities to Kingdom {KingdomId}", entitiesList.Count, typeof(T).Name, kingdomId);

                // Validate all entities have correct kingdom ID
                foreach (var entity in entitiesList)
                {
                    if (entity.KingdomId != kingdomId)
                    {
                        throw new ArgumentException($"All entities must have kingdom ID {kingdomId}, found entity with kingdom ID {entity.KingdomId}");
                    }
                }

                await _dbSet.AddRangeAsync(entitiesList, cancellationToken);

                _logger.LogDebug("Successfully added {Count} {EntityType} entities to Kingdom {KingdomId}", entitiesList.Count, typeof(T).Name, kingdomId);

                return entitiesList;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Add range {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error adding multiple {EntityType} entities to Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to add multiple {typeof(T).Name} entities", ex);
            }
        }

        /// <summary>
        /// Updates existing entity with kingdom validation
        /// </summary>
        public virtual async Task<T> UpdateAsync(T entity, int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException(nameof(entity));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Updating {EntityType} in Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                // Validate kingdom ID matches
                if (entity.KingdomId != kingdomId)
                {
                    throw new ArgumentException($"Entity kingdom ID ({entity.KingdomId}) must match provided kingdom ID ({kingdomId})");
                }

                _context.Entry(entity).State = EntityState.Modified;

                _logger.LogDebug("Successfully updated {EntityType} in Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                return entity;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating {EntityType} in Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to update {typeof(T).Name}", ex);
            }
        }

        /// <summary>
        /// Updates multiple entities with kingdom validation
        /// </summary>
        public virtual async Task<IEnumerable<T>> UpdateRangeAsync(IEnumerable<T> entities, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (entities == null)
                    throw new ArgumentNullException(nameof(entities));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                var entitiesList = entities.ToList();
                if (!entitiesList.Any())
                    return new List<T>();

                _logger.LogDebug("Updating {Count} {EntityType} entities in Kingdom {KingdomId}", entitiesList.Count, typeof(T).Name, kingdomId);

                // Validate all entities have correct kingdom ID
                foreach (var entity in entitiesList)
                {
                    if (entity.KingdomId != kingdomId)
                    {
                        throw new ArgumentException($"All entities must have kingdom ID {kingdomId}, found entity with kingdom ID {entity.KingdomId}");
                    }
                }

                _dbSet.UpdateRange(entitiesList);

                _logger.LogDebug("Successfully updated {Count} {EntityType} entities in Kingdom {KingdomId}", entitiesList.Count, typeof(T).Name, kingdomId);

                return entitiesList;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating multiple {EntityType} entities in Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to update multiple {typeof(T).Name} entities", ex);
            }
        }

        /// <summary>
        /// Deletes entity by ID with kingdom validation
        /// </summary>
        public virtual async Task<bool> DeleteAsync(K id, int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Deleting {EntityType} with ID {Id} from Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);

                var entity = await GetByIdAsync(id, kingdomId, cancellationToken);
                if (entity == null)
                {
                    _logger.LogDebug("Entity {EntityType} with ID {Id} not found in Kingdom {KingdomId} for deletion", typeof(T).Name, id, kingdomId);
                    return false;
                }

                _dbSet.Remove(entity);

                _logger.LogDebug("Successfully deleted {EntityType} with ID {Id} from Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);
                return true;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Delete {EntityType} by ID operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting {EntityType} with ID {Id} from Kingdom {KingdomId}", typeof(T).Name, id, kingdomId);
                throw new InvalidOperationException($"Failed to delete {typeof(T).Name} with ID {id}", ex);
            }
        }

        /// <summary>
        /// Deletes entity with kingdom validation
        /// </summary>
        public virtual async Task<bool> DeleteAsync(T entity, int kingdomId, CancellationToken cancellationToken = default)
        {
            try
            {
                if (entity == null)
                    throw new ArgumentNullException(nameof(entity));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Deleting {EntityType} from Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                // Validate kingdom ID matches
                if (entity.KingdomId != kingdomId)
                {
                    throw new ArgumentException($"Entity kingdom ID ({entity.KingdomId}) must match provided kingdom ID ({kingdomId})");
                }

                _dbSet.Remove(entity);

                _logger.LogDebug("Successfully deleted {EntityType} from Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting {EntityType} from Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to delete {typeof(T).Name}", ex);
            }
        }

        /// <summary>
        /// Deletes entities matching predicate with kingdom validation
        /// </summary>
        public virtual async Task<int> DeleteWhereAsync(Expression<Func<T, bool>> predicate, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            try
            {
                if (predicate == null)
                    throw new ArgumentNullException(nameof(predicate));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Deleting {EntityType} entities matching predicate from Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                var entities = await _dbSet
                    .Where(e => e.KingdomId == kingdomId)
                    .Where(predicate)
                    .ToListAsync(cancellationToken);

                if (!entities.Any())
                {
                    _logger.LogDebug("No {EntityType} entities found matching predicate for deletion in Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                    return 0;
                }

                _dbSet.RemoveRange(entities);

                _logger.LogDebug("Successfully deleted {Count} {EntityType} entities matching predicate from Kingdom {KingdomId}",
                    entities.Count, typeof(T).Name, kingdomId);

                return entities.Count;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Delete where {EntityType} operation cancelled", typeof(T).Name);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting {EntityType} entities matching predicate from Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to delete {typeof(T).Name} entities matching predicate", ex);
            }
        }

        #endregion

        #region Transaction and Performance Operations

        /// <summary>
        /// Executes operation within transaction scope
        /// </summary>
        public virtual async Task<TResult> ExecuteInTransactionAsync<TResult>(Func<Task<TResult>> operation, int kingdomId,
            CancellationToken cancellationToken = default)
        {
            if (operation == null)
                throw new ArgumentNullException(nameof(operation));
            if (kingdomId <= 0)
                throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

            _logger.LogDebug("Executing operation in transaction for Kingdom {KingdomId}", kingdomId);

            using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);
            try
            {
                var result = await operation();
                await transaction.CommitAsync(cancellationToken);

                _logger.LogDebug("Transaction completed successfully for Kingdom {KingdomId}", kingdomId);
                return result;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Transaction operation cancelled for Kingdom {KingdomId}", kingdomId);
                await transaction.RollbackAsync(CancellationToken.None);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Transaction failed for Kingdom {KingdomId}, rolling back", kingdomId);
                await transaction.RollbackAsync(CancellationToken.None);
                throw new InvalidOperationException("Transaction operation failed", ex);
            }
        }

        /// <summary>
        /// Executes raw SQL query with kingdom scoping
        /// </summary>
        public virtual async Task<IEnumerable<T>> ExecuteRawSqlAsync(string sql, int kingdomId,
            CancellationToken cancellationToken = default, params object[] parameters)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(sql))
                    throw new ArgumentException("SQL query cannot be null or empty", nameof(sql));
                if (kingdomId <= 0)
                    throw new ArgumentException("Kingdom ID must be positive", nameof(kingdomId));

                _logger.LogDebug("Executing raw SQL for {EntityType} in Kingdom {KingdomId}", typeof(T).Name, kingdomId);

                // Ensure the SQL includes kingdom filtering for security
                var kingdomFilteredSql = sql.Contains("WHERE", StringComparison.OrdinalIgnoreCase)
                    ? $"{sql} AND KingdomId = {kingdomId}"
                    : $"{sql} WHERE KingdomId = {kingdomId}";

                var result = await _dbSet
                    .FromSqlRaw(kingdomFilteredSql, parameters)
                    .ToListAsync(cancellationToken);

                _logger.LogDebug("Raw SQL returned {Count} {EntityType} entities for Kingdom {KingdomId}",
                    result.Count, typeof(T).Name, kingdomId);

                return result;
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Raw SQL execution cancelled for Kingdom {KingdomId}", kingdomId);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error executing raw SQL for {EntityType} in Kingdom {KingdomId}", typeof(T).Name, kingdomId);
                throw new InvalidOperationException($"Failed to execute raw SQL for {typeof(T).Name}", ex);
            }
        }

        #endregion
    }
}