using AutoMapper;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Master;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Helpers;
using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace MarcoBMS.Services.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    // [Authorize]
    public class FeatureController : ControllerBase
    {
        private readonly ApplicationDbContext _context;
        private readonly GeneralHelper _generalHelper;
        //private readonly UserHelper _userHelper;
        private readonly IMapper _mapper;
        private readonly ILoggingService _logger;
        private readonly Guid tenantId;

        public FeatureController(ApplicationDbContext context, GeneralHelper generalHelper, UserHelper userHelper, IMapper mapper, ILoggingService logger)
        {
            _context = context;
            _generalHelper = generalHelper;
            //_userHelper = userHelper;
            _mapper = mapper;
            _logger = logger;
            tenantId = userHelper.GetTenantId();
        }

        /// <summary>
        /// Converts FeaturePermissions from Feature entity into FeaturePermissionVM collection.
        /// </summary>
        /// <param name="model">Feature entity from DB</param>
        /// <returns>Collection of FeaturePermissionVM, ordered by Name</returns>
        private ICollection<FeaturePermissionVM> GetFeaturePermissionVMs(Feature model)
        {
            if (model.FeaturePermissions == null || !model.FeaturePermissions.Any())
            {
                _logger.LogInfo("No feature permissions found for Feature: {FeatureId}", model.Id);
                return new List<FeaturePermissionVM>();
            }

            // Project and order feature permissions
            var features = model.FeaturePermissions
                .Select(p => _mapper.Map<FeaturePermissionVM>(p))
                .OrderBy(f => f.Name)
                .ToList();

            _logger.LogDebug("Mapped {Count} feature permissions for Feature: {FeatureId}", features.Count, model.Id);
            return features;
        }

        /// <summary>
        /// API endpoint to fetch all features and their permissions for the given tenant.
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> GetAllFeaturesAsync()
        {
            try
            {
                _logger.LogInfo("Fetching all features for tenant: {TenantId}", tenantId);

                var featureQuery = _context.Features
                    .AsNoTracking(); // Optimization: Read-only query
                if (tenantId != Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"))
                {

                    // Step 1: Get tenant-specific FeatureIds
                    List<Guid> featureIds = await _generalHelper.GetFeatureIdsByTenentIdAsync(tenantId);
                    if (featureIds == null || !featureIds.Any())
                    {
                        _logger.LogWarning("No features found for tenant: {TenantId}", tenantId);
                        return Ok(ApiResponse<object>.SuccessResponse(new List<FeatureVM>(), "No features found.", 200));
                    }
                    _logger.LogDebug("Retrieved {Count} feature IDs for tenant: {TenantId}", featureIds.Count, tenantId);

                    // Step 2: Query Features with related FeaturePermissions & Module
                    featureQuery = featureQuery.Where(f => featureIds.Contains(f.Id));
                }

                var features = await featureQuery
                        .Include(f => f.FeaturePermissions)
                        .Include(f => f.Module).ToListAsync();
                _logger.LogDebug("Fetched {Count} features from DB for tenant: {TenantId}", features.Count, tenantId);

                // Step 3: Map features to ViewModels
                var featureVMs = features
                    .Select(c => new FeatureVM
                    {
                        Id = c.Id,
                        Name = c.Name,
                        Description = c.Description,
                        FeaturePermissions = GetFeaturePermissionVMs(c),
                        ModuleId = c.ModuleId,
                        ModuleName = c.Module?.Name ?? string.Empty,
                        IsActive = c.IsActive
                    })
                    .OrderBy(f => f.Name)
                    .ToList();

                _logger.LogInfo("Returning {Count} features for tenant: {TenantId}", featureVMs.Count, tenantId);

                return Ok(ApiResponse<object>.SuccessResponse(featureVMs, "Success.", 200));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error while fetching features for tenant: {TenantId}", tenantId);
                return StatusCode(500, ApiResponse<object>.ErrorResponse("An unexpected error occurred.", 500));
            }
        }
    }
}
