using AutoMapper;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Dtos.Attendance;
using Marco.Pms.Model.Dtos.Employees;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.Employee;
using Marco.Pms.Services.Helpers;
using Marco.Pms.Services.Hubs;
using Marco.Pms.Services.Service;
using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Service;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using System.Data;
using System.Net;

namespace MarcoBMS.Services.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]

    public class EmployeeController : ControllerBase
    {

        private readonly ApplicationDbContext _context;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly IEmailSender _emailSender;
        private readonly EmployeeHelper _employeeHelper;
        private readonly UserHelper _userHelper;
        private readonly GeneralHelper _generalHelper;
        private readonly IConfiguration _configuration;
        private readonly ILoggingService _logger;
        private readonly IHubContext<MarcoHub> _signalR;
        private readonly PermissionServices _permission;
        private readonly IMapper _mapper;
        private readonly IProjectServices _projectServices;
        private readonly Guid tenantId;


        public EmployeeController(UserManager<ApplicationUser> userManager, IEmailSender emailSender,
            ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration, ILoggingService logger,
            IHubContext<MarcoHub> signalR, PermissionServices permission, IProjectServices projectServices, IMapper mapper, GeneralHelper generalHelper)
        {
            _context = context;
            _userManager = userManager;
            _emailSender = emailSender;
            _employeeHelper = employeeHelper;
            _userHelper = userHelper;
            _generalHelper = generalHelper;
            _configuration = configuration;
            _logger = logger;
            _signalR = signalR;
            _permission = permission;
            _projectServices = projectServices;
            _mapper = mapper;
            tenantId = _userHelper.GetTenantId();
        }

        [HttpGet]
        [Route("roles/{employeeId?}")]
        public async Task<IActionResult> GetRoles(Guid employeeId)
        {
            if (!ModelState.IsValid)
            {
                var errors = ModelState.Values
                    .SelectMany(v => v.Errors)
                    .Select(e => e.ErrorMessage)
                    .ToList();
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
            }
            Guid tenantId = GetTenantId();

            var empRoles = await _context.EmployeeRoleMappings.Where(c => c.EmployeeId == employeeId).Include(c => c.Role).Include(c => c.Employee).ToListAsync();
            if (empRoles.Any())
            {
                List<EmployeeRolesVM> roles = new List<EmployeeRolesVM>();

                foreach (EmployeeRoleMapping mapping in empRoles)
                {
                    roles.Add(new EmployeeRolesVM()
                    {
                        Id = mapping.Id,
                        EmployeeId = mapping.EmployeeId,
                        Name = mapping.Role != null ? mapping.Role.Role : null,
                        Description = mapping.Role != null ? mapping.Role.Description : null,
                        IsEnabled = mapping.IsEnabled,
                        RoleId = mapping.RoleId,
                    });
                }
                return Ok(ApiResponse<object>.SuccessResponse(roles, "Success.", 200));
            }
            else
            {
                return BadRequest(ApiResponse<object>.ErrorResponse("This employee has no assigned permissions.", "This employee has no assigned permissions.", 400));
            }
        }

        [HttpGet]
        [Route("list/{projectid?}")]
        public async Task<IActionResult> GetEmployeesByProject(Guid? projectid, [FromQuery] bool ShowInactive)
        {
            // Step 1: Validate incoming request model state
            if (!ModelState.IsValid)
            {
                var errors = ModelState.Values
                    .SelectMany(v => v.Errors)
                    .Select(e => e.ErrorMessage)
                    .ToList();

                _logger.LogWarning("Invalid model state in GetEmployeesByProject. Errors: {@Errors}", errors);
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
            }

            // Step 2: Get logged-in employee
            var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
            _logger.LogInfo("GetEmployeesByProject called by EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, ShowInactive: {ShowInactive}",
                loggedInEmployee.Id, projectid ?? Guid.Empty, ShowInactive);

            // Step 3: Fetch project access and permissions
            var projectIds = await _projectServices.GetMyProjectIdsAsync(tenantId, loggedInEmployee);

            var hasViewAllEmployeesPermission = await _permission.HasPermission(PermissionsMaster.ViewAllEmployees, loggedInEmployee.Id);
            var hasViewTeamMembersPermission = await _permission.HasPermission(PermissionsMaster.ViewTeamMembers, loggedInEmployee.Id);

            List<EmployeeVM> result = new();

            // Step 4: Determine access level and fetch employees accordingly
            if (hasViewAllEmployeesPermission || projectid != null)
            {
                result = await _employeeHelper.GetEmployeeByProjectId(tenantId, projectid, ShowInactive);
                _logger.LogInfo("Employee list fetched using full access or specific project.");
            }
            else if (hasViewTeamMembersPermission && !ShowInactive)
            {
                var employeeIds = await _context.ProjectAllocations
                    .Where(pa => projectIds.Contains(pa.ProjectId) && pa.IsActive && pa.TenantId == tenantId)
                    .Select(pa => pa.EmployeeId)
                    .Distinct()
                    .ToListAsync();

                result = await _context.Employees
                    .Include(fp => fp.JobRole)
                    .Where(e => employeeIds.Contains(e.Id) && e.IsActive && e.TenantId == tenantId)
                    .Select(e => e.ToEmployeeVMFromEmployee())
                    .Distinct()
                    .ToListAsync();

                _logger.LogInfo("Employee list fetched using limited access (active only).");
            }
            else
            {
                _logger.LogWarning("Access denied for EmployeeId: {EmployeeId} - insufficient permissions.", loggedInEmployee.Id);
                return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200));
            }

            // Step 5: Log and return results
            _logger.LogInfo("Employees fetched successfully by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}. Count: {Count}",
                loggedInEmployee.Id, projectid ?? Guid.Empty, result.Count);

            return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200));
        }

        [HttpGet("basic")]
        public async Task<IActionResult> GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString)
        {
            var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
            var employeeQuery = _context.Employees.Where(e => e.TenantId == tenantId);
            if (projectId != null && projectId != Guid.Empty)
            {
                var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value);
                if (!hasProjectPermission)
                {
                    _logger.LogWarning("User {EmployeeId} attempts to get employee for project {ProjectId}, but not have access to the project", loggedInEmployee.Id, projectId);
                    return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "User do not have access to view the list for this project", 403));
                }
                var employeeIds = await _context.ProjectAllocations.Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.TenantId == tenantId).Select(p => p.EmployeeId).ToListAsync();
                employeeQuery = employeeQuery.Where(e => employeeIds.Contains(e.Id));
            }
            if (!string.IsNullOrWhiteSpace(searchString))
            {
                var searchStringLower = searchString.ToLower();
                employeeQuery = employeeQuery.Where(e => (e.FirstName + " " + e.LastName).ToLower().Contains(searchStringLower));
            }

            var response = await employeeQuery.Take(10).Select(e => _mapper.Map<BasicEmployeeVM>(e)).ToListAsync();
            return Ok(ApiResponse<object>.SuccessResponse(response, $"{response.Count} records of employees fetched successfully", 200));
        }

        /// <summary>
        /// Retrieves a paginated list of employees assigned to a specified project (if provided),
        /// with optional search functionality. 
        /// Ensures that the logged-in user has necessary permissions before accessing project employees.
        /// </summary>
        /// <param name="projectId">Optional project identifier to filter employees by project.</param>
        /// <param name="searchString">Optional search string to filter employees by name.</param>
        /// <param name="pageNumber">Page number for pagination (default = 1).</param>
        /// <returns>Paginated list of employees in BasicEmployeeVM format wrapped in ApiResponse.</returns>

        [HttpGet("search")]
        public async Task<IActionResult> GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString,
            [FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10)
        {
            // Log API entry with context
            _logger.LogInfo("Fetching employees. ProjectId: {ProjectId}, SearchString: {SearchString}, PageNumber: {PageNumber}",
                                    projectId ?? Guid.Empty, searchString ?? "", pageNumber);

            var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
            _logger.LogDebug("Logged-in EmployeeId: {EmployeeId}", loggedInEmployee.Id);

            // Initialize query scoped by tenant
            var employeeQuery = _context.Employees.Where(e => e.TenantId == tenantId);

            // Filter by project if projectId is supplied
            if (projectId.HasValue && projectId.Value != Guid.Empty)
            {
                _logger.LogDebug("Project filter applied. Checking permission for EmployeeId: {EmployeeId} on ProjectId: {ProjectId}",
                                 loggedInEmployee.Id, projectId);

                // Validate project access permission
                var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value);
                if (!hasProjectPermission)
                {
                    _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have permission for ProjectId: {ProjectId}",
                                       loggedInEmployee.Id, projectId);

                    return StatusCode(403, ApiResponse<object>.ErrorResponse(
                        "Access denied",
                        "User does not have access to view employees for this project",
                        403));
                }

                // Employees allocated to the project
                var employeeIds = await _context.ProjectAllocations
                                                .Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.TenantId == tenantId)
                                                .Select(pa => pa.EmployeeId)
                                                .ToListAsync();

                _logger.LogDebug("Project employees retrieved. Total linked employees found: {Count}", employeeIds.Count);

                // Apply project allocation filter
                employeeQuery = employeeQuery.Where(e => employeeIds.Contains(e.Id));
            }

            // Apply search filter if provided
            if (!string.IsNullOrWhiteSpace(searchString))
            {
                var searchStringLower = searchString.ToLower();
                _logger.LogDebug("Search filter applied. Search term: {SearchTerm}", searchStringLower);

                employeeQuery = employeeQuery.Where(e =>
                    (e.FirstName + " " + e.LastName).ToLower().Contains(searchStringLower));
            }

            // Pagination and Projection (executed in DB)
            var employees = await employeeQuery
                .Skip((pageNumber - 1) * pageSize)
                .Take(pageSize)
                .Select(e => _mapper.Map<BasicEmployeeVM>(e))
                .ToListAsync();

            _logger.LogInfo("Employees fetched successfully. Records returned: {Count}", employees.Count);

            return Ok(ApiResponse<object>.SuccessResponse(
                employees,
                $"{employees.Count} employee records fetched successfully",
                200));
        }


        [HttpGet]
        [Route("profile/get/{employeeId}")]
        public async Task<IActionResult> GetEmployeeProfileById(Guid employeeId)
        {
            if (!ModelState.IsValid)
            {
                var errors = ModelState.Values
                    .SelectMany(v => v.Errors)
                    .Select(e => e.ErrorMessage)
                    .ToList();
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
            }

            Employee emp = await _employeeHelper.GetEmployeeByID(employeeId);
            EmployeeVM employeeVM = EmployeeMapper.ToEmployeeVMFromEmployee(emp);

            return Ok(ApiResponse<object>.SuccessResponse(employeeVM, "Employee Profile.", 200));
        }

        private Guid GetTenantId()
        {
            return _userHelper.GetTenantId();
        }


        [HttpPost("manage")]
        public async Task<IActionResult> CreateUser([FromBody] CreateUserDto model)
        {
            Guid tenantId = _userHelper.GetTenantId();
            var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
            Guid employeeId = Guid.Empty;
            if (model == null)
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", "Invaild Data", 400));

            if (model.FirstName == null && model.PhoneNumber == null)
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", "Invaild Data", 400));

            string responsemessage = "";

            if (model.Email != null)
            {
                // Check if user already exists by email
                IdentityUser? existingUser = await _userHelper.GetRegisteredUser(model.Email);
                var existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id && e.IsActive == true);

                if (existingUser != null)
                {
                    /* Identity user Exists - Create/update employee Employee */

                    // Update Employee record
                    existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Email == model.Email && e.Id == model.Id && e.IsActive == true);
                    if (existingEmployee != null)
                    {
                        existingEmployee = GetUpdateEmployeeModel(model, existingEmployee, existingUser);

                        _context.Employees.Update(existingEmployee);
                        await _context.SaveChangesAsync();
                        employeeId = existingEmployee.Id;
                        responsemessage = "User updated successfully.";
                    }
                    else
                    {
                        // Create Employee record if missing
                        //Employee newEmployee = GetNewEmployeeModel(model, TenantId, existingUser.Id);
                        //_context.Employees.Add(newEmployee);
                        return Conflict(ApiResponse<object>.ErrorResponse("Email already exist", "Email already exist", 409));
                    }


                }
                else
                {
                    var user = new ApplicationUser
                    {
                        UserName = model.Email,
                        Email = model.Email,
                        EmailConfirmed = true,
                        TenantId = tenantId

                    };
                    var isSeatsAvaiable = await _generalHelper.CheckSeatsRemainingAsync(tenantId);
                    if (!isSeatsAvaiable)
                    {
                        _logger.LogWarning("Maximum number of users reached for Tenant {TenantId}", tenantId);
                        return BadRequest(ApiResponse<object>.ErrorResponse("Maximum number of users reached. Cannot add new user", "Maximum number of users reached. Cannot add new user", 400));
                    }
                    // Create Identity User
                    var result = await _userManager.CreateAsync(user, "User@123");
                    if (!result.Succeeded)
                        return BadRequest(ApiResponse<object>.ErrorResponse("Failed to create user", result.Errors, 400));

                    if (existingEmployee == null)
                    {
                        Employee newEmployee = GetNewEmployeeModel(model, tenantId, user.Id);
                        _context.Employees.Add(newEmployee);

                        await _context.SaveChangesAsync();
                        employeeId = newEmployee.Id;

                        /* SEND USER REGISTRATION MAIL*/
                        var token = await _userManager.GeneratePasswordResetTokenAsync(user);
                        var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}";
                        if (newEmployee.FirstName != null)
                        {
                            await _emailSender.SendResetPasswordEmailOnRegister(user.Email, newEmployee.FirstName, resetLink);
                        }

                    }
                    else
                    {
                        existingEmployee.Email = model.Email;
                        existingEmployee = GetUpdateEmployeeModel(model, existingEmployee, user);

                        _context.Employees.Update(existingEmployee);
                        await _context.SaveChangesAsync();

                        employeeId = existingEmployee.Id;

                        /* SEND USER REGISTRATION MAIL*/
                        var token = await _userManager.GeneratePasswordResetTokenAsync(user);
                        var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}";
                        if (existingEmployee.FirstName != null)
                        {
                            await _emailSender.SendResetPasswordEmailOnRegister(user.Email, existingEmployee.FirstName, resetLink);
                        }

                    }


                    responsemessage = "User created successfully. Password reset link is sent to registered email";
                }
            }
            else
            {
                var existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id && e.IsActive == true);
                if (existingEmployee != null)
                {
                    existingEmployee = GetUpdateEmployeeModel(model, existingEmployee);
                    _context.Employees.Update(existingEmployee);
                    responsemessage = "User updated successfully.";
                    employeeId = existingEmployee.Id;
                }
                else
                {
                    // Create Employee record if missing
                    Employee newEmployee = GetNewEmployeeModel(model, tenantId, string.Empty);
                    _context.Employees.Add(newEmployee);
                    employeeId = newEmployee.Id;
                }
                await _context.SaveChangesAsync();
                responsemessage = "User created successfully.";

            }
            var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Employee", EmployeeId = employeeId };

            await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
            return Ok(ApiResponse<object>.SuccessResponse("Success.", responsemessage, 200));
        }

        [HttpPost("manage-mobile")]
        public async Task<IActionResult> CreateUserMoblie([FromBody] MobileUserManageDto model)
        {
            Guid tenantId = _userHelper.GetTenantId();
            if (model == null)
            {
                _logger.LogWarning("User submitted empty or null employee information during employee creation or update in tenant {TenantId}", tenantId);
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", "Invaild Data", 400));
            }

            if (string.IsNullOrWhiteSpace(model.FirstName) || string.IsNullOrWhiteSpace(model.PhoneNumber))
            {
                _logger.LogWarning("User submitted empty or null first name or phone number during employee creation or update in tenant {TenantId}", tenantId);
                return BadRequest(ApiResponse<object>.ErrorResponse("First name and phone number are required fields.", "First name and phone number are required fields.", 400));
            }

            if (model.Id == null)
            {
                byte[]? imageBytes = null;
                if (!string.IsNullOrWhiteSpace(model.ProfileImage))
                {
                    try
                    {
                        imageBytes = Convert.FromBase64String(model.ProfileImage);
                    }
                    catch (FormatException)
                    {
                        return BadRequest(ApiResponse<object>.ErrorResponse("Invalid image format.", "Invalid image format", 400));
                    }
                }
                Employee employee = model.ToEmployeeFromMobileUserManageDto(tenantId, imageBytes);
                _context.Employees.Add(employee);
                await _context.SaveChangesAsync();

                EmployeeVM employeeVM = employee.ToEmployeeVMFromEmployee();

                _logger.LogInfo($"Employee {employee.FirstName} {employee.LastName} created in tenant {tenantId}");
                return Ok(ApiResponse<object>.SuccessResponse(employeeVM, "Employee created successfully", 200));
            }
            else
            {
                Employee? existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id.Value);
                if (existingEmployee == null)
                {
                    _logger.LogWarning("User tries to update employee {EmployeeId} but not found in database", model.Id);
                    return NotFound(ApiResponse<object>.ErrorResponse("Employee not found", "Employee not found", 404));
                }
                byte[]? imageBytes = null;
                if (!string.IsNullOrWhiteSpace(model.ProfileImage))
                {
                    try
                    {
                        imageBytes = Convert.FromBase64String(model.ProfileImage);
                    }
                    catch (FormatException)
                    {
                        return BadRequest(ApiResponse<object>.ErrorResponse("Invalid image format.", "Invalid image format", 400));
                    }
                }

                imageBytes ??= existingEmployee.Photo;

                existingEmployee.FirstName = model.FirstName;
                existingEmployee.LastName = model.LastName;
                existingEmployee.Gender = model.Gender;
                existingEmployee.PhoneNumber = model.PhoneNumber;
                existingEmployee.JoiningDate = model.JoiningDate;
                existingEmployee.JobRoleId = model.JobRoleId;
                existingEmployee.Photo = imageBytes;

                await _context.SaveChangesAsync();

                EmployeeVM employeeVM = existingEmployee.ToEmployeeVMFromEmployee();

                _logger.LogInfo($"Employee {existingEmployee.FirstName} {existingEmployee.LastName} updated in tenant {tenantId}");
                return Ok(ApiResponse<object>.SuccessResponse(employeeVM, "Employee updated successfully", 200));
            }
        }

        [HttpDelete("{id}")]
        public async Task<IActionResult> SuspendEmployee(Guid id, [FromQuery] bool active = false)
        {
            Guid tenantId = _userHelper.GetTenantId();
            var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync();
            Employee? employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == id && e.TenantId == tenantId);
            if (employee == null)
            {
                _logger.LogWarning("Employee with ID {EmploueeId} not found in database", id);
                return NotFound(ApiResponse<object>.ErrorResponse("Employee Not found successfully", "Employee Not found successfully", 404));
            }
            if (employee.IsSystem)
            {
                _logger.LogWarning("Employee with ID {LoggedEmployeeId} tries to suspend system-defined employee with ID {EmployeeId}", LoggedEmployee.Id, employee.Id);
                return BadRequest(ApiResponse<object>.ErrorResponse("System-defined employees cannot be suspended.", "System-defined employees cannot be suspended.", 400));
            }
            var assignedToTasks = await _context.TaskMembers.Where(t => t.EmployeeId == employee.Id).ToListAsync();
            if (assignedToTasks.Count != 0)
            {
                List<Guid> taskIds = assignedToTasks.Select(t => t.TaskAllocationId).ToList();
                var tasks = await _context.TaskAllocations.Where(t => taskIds.Contains(t.Id)).ToListAsync();

                foreach (var assignedToTask in assignedToTasks)
                {
                    var task = tasks.Find(t => t.Id == assignedToTask.TaskAllocationId);
                    if (task != null && task.CompletedTask == 0)
                    {
                        _logger.LogWarning("Employee with ID {EmployeeId} is currently assigned to any incomplete task", employee.Id);
                        return BadRequest(ApiResponse<object>.ErrorResponse("Employee is currently assigned to any incomplete task", "Employee is currently assigned to any incomplete task", 400));
                    }
                }
            }
            var attendance = await _context.Attendes.Where(a => a.EmployeeID == employee.Id && (a.OutTime == null || a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE)).ToListAsync();
            if (attendance.Count != 0)
            {
                _logger.LogWarning("Employee with ID {EmployeeId} have any pending check-out or regularization requests", employee.Id);
                return BadRequest(ApiResponse<object>.ErrorResponse("Employee have any pending check-out or regularization requests", "Employee have any pending check-out or regularization requests", 400));
            }
            if (active)
            {
                employee.IsActive = true;
                var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Id == employee.ApplicationUserId);
                if (user != null)
                {
                    user.IsActive = true;
                    _logger.LogInfo("The application user associated with employee ID {EmployeeId} has been actived.", employee.Id);

                }
                _logger.LogInfo("Employee with ID {EmployeId} Actived successfully", employee.Id);
            }
            else
            {
                employee.IsActive = false;
                var projectAllocations = await _context.ProjectAllocations.Where(a => a.EmployeeId == employee.Id).ToListAsync();
                if (projectAllocations.Count != 0)
                {
                    List<ProjectAllocation> allocations = new List<ProjectAllocation>();
                    foreach (var projectAllocation in projectAllocations)
                    {
                        projectAllocation.ReAllocationDate = DateTime.UtcNow;
                        projectAllocation.IsActive = false;
                        allocations.Add(projectAllocation);
                    }
                    _logger.LogInfo("Employee with ID {EmployeeId} has been removed from all assigned projects.", employee.Id);
                }
                var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Id == employee.ApplicationUserId);
                if (user != null)
                {
                    user.IsActive = false;
                    _logger.LogInfo("The application user associated with employee ID {EmployeeId} has been suspended.", employee.Id);

                    var refreshTokens = await _context.RefreshTokens.AsNoTracking().Where(t => t.UserId == user.Id).ToListAsync();
                    if (refreshTokens.Count != 0)
                    {
                        _context.RefreshTokens.RemoveRange(refreshTokens);
                        _logger.LogInfo("Refresh tokens associated with employee ID {EmployeeId} has been removed.", employee.Id);
                    }

                }
                var roleMapping = await _context.EmployeeRoleMappings.AsNoTracking().Where(r => r.EmployeeId == employee.Id).ToListAsync();
                if (roleMapping.Count != 0)
                {
                    _context.EmployeeRoleMappings.RemoveRange(roleMapping);
                    _logger.LogInfo("Application role mapping associated with employee ID {EmployeeId} has been removed.", employee.Id);
                }
                _logger.LogInfo("Employee with ID {EmployeId} Deleted successfully", employee.Id);
            }
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException ex)
            {
                _logger.LogError(ex, "Exception Occured While activting/deactivting employee {EmployeeId}", employee.Id);
                return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Error Occured", "Error occured while saving the entity", 500));
            }
            var notification = new { LoggedInUserId = LoggedEmployee.Id, Keyword = "Employee", EmployeeId = employee.Id };

            await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
            return Ok(ApiResponse<object>.SuccessResponse(new { }, "Employee Suspended successfully", 200));
        }
        private static Employee GetNewEmployeeModel(CreateUserDto model, Guid TenantId, string ApplicationUserId)
        {
            var newEmployee = new Employee
            {
                ApplicationUserId = String.IsNullOrEmpty(ApplicationUserId) ? null : ApplicationUserId,
                FirstName = model.FirstName,
                LastName = model.LastName,
                Email = model.Email,
                TenantId = TenantId,
                CurrentAddress = model.CurrentAddress,
                BirthDate = Convert.ToDateTime(model.BirthDate),
                EmergencyPhoneNumber = model.EmergencyPhoneNumber,
                EmergencyContactPerson = model.EmergencyContactPerson,
                AadharNumber = model.AadharNumber,
                Gender = model.Gender,
                MiddleName = model.MiddleName,
                PanNumber = model.PanNumber,
                PermanentAddress = model.PermanentAddress,
                PhoneNumber = model.PhoneNumber,
                Photo = null, // GetFileDetails(model.Photo).Result.FileData,
                JobRoleId = model.JobRoleId,
                JoiningDate = Convert.ToDateTime(model.JoiningDate),

            };
            return newEmployee;
        }
        private static Employee GetUpdateEmployeeModel(CreateUserDto model, Employee existingEmployee, IdentityUser? existingIdentityUser = null)
        {
            if (existingEmployee.ApplicationUserId == null && existingIdentityUser != null)
            {
                existingEmployee.ApplicationUserId = existingIdentityUser.Id;
            }
            existingEmployee.FirstName = model.FirstName;
            existingEmployee.LastName = model.LastName;
            existingEmployee.CurrentAddress = model.CurrentAddress;
            existingEmployee.BirthDate = Convert.ToDateTime(model.BirthDate);
            existingEmployee.JoiningDate = Convert.ToDateTime(model.JoiningDate);
            existingEmployee.EmergencyPhoneNumber = model.EmergencyPhoneNumber;
            existingEmployee.EmergencyContactPerson = model.EmergencyContactPerson;
            existingEmployee.AadharNumber = model.AadharNumber;
            existingEmployee.Gender = model.Gender;
            existingEmployee.MiddleName = model.MiddleName;
            existingEmployee.PanNumber = model.PanNumber;
            existingEmployee.PermanentAddress = model.PermanentAddress;
            existingEmployee.PhoneNumber = model.PhoneNumber;
            existingEmployee.Photo = existingEmployee.Photo; // GetFileDetails(model.Photo).Result.FileData,
            existingEmployee.JobRoleId = model.JobRoleId;

            return existingEmployee;
        }
        private static async Task<FileDetails> GetFileDetails(IFormFile file)
        {
            FileDetails info = new FileDetails();
            info.ContentType = file.ContentType;
            info.FileName = file.FileName;

            using (var memoryStream = new MemoryStream())
            {
                await file.CopyToAsync(memoryStream);
                info.FileData = memoryStream.ToArray();
            }
            return info;

        }
    }
}
