
using AutoMapper;
using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Mapper;
using Marco.Pms.Model.ViewModels.Employee;
using MarcoBMS.Services.Service;
using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore;

namespace MarcoBMS.Services.Helpers
{
    public class EmployeeHelper
    {
        private readonly ApplicationDbContext _context;
        private readonly ILoggingService _logger;
        private readonly IMapper _mapper;
        public EmployeeHelper(ApplicationDbContext context, ILoggingService logger, IMapper mapper)
        {
            _context = context;
            _logger = logger;
            _mapper = mapper;
        }
        public async Task<Employee> GetEmployeeByID(Guid EmployeeID)
        {

            return await _context.Employees.Include(e => e.JobRole).Include(e => e.Organization).FirstOrDefaultAsync(e => e.Id == EmployeeID) ?? new Employee { };
        }

        public async Task<Employee> GetEmployeeByApplicationUserID(string ApplicationUserID)
        {
            try
            {
                var result = await _context.Employees.Where(c => c.ApplicationUserId == ApplicationUserID && c.IsActive == true).ToListAsync();

                return await _context.Employees.Include(e => e.ApplicationUser).Where(c => c.ApplicationUserId == ApplicationUserID && c.ApplicationUser != null && c.IsActive == true).SingleOrDefaultAsync() ?? new Employee { };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occured while fetching employee by application user ID {ApplicationUserId}", ApplicationUserID);
                return new Employee();
            }
        }

        public async Task<List<EmployeeVM>> SearchEmployeeByProjectId(Guid TenentId, string searchString, Guid? ProjectId)
        {
            try
            {
                List<EmployeeVM> result = new List<EmployeeVM>();
                if (ProjectId != null)
                {

                    result = await (from pa in _context.ProjectAllocations.Where(c => c.ProjectId == ProjectId)
                                    join em in _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == true).Include(fp => fp.JobRole) // Include Feature
                    on pa.EmployeeId equals em.Id
                                    where (em.FirstName != null ? em.FirstName.ToLower().Contains(searchString.ToLower()) : false) || (em.LastName != null ? em.LastName.ToLower().Contains(searchString.ToLower()) : false)
                                    select em.ToEmployeeVMFromEmployee()
                                       )
                        .ToListAsync();

                }
                else
                {
                    result = await _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == true &&
                            ((c.FirstName != null ? c.FirstName.ToLower().Contains(searchString.ToLower()) : false) || (c.LastName != null ? c.LastName.ToLower().Contains(searchString.ToLower()) : false))).Include(fp => fp.JobRole)
                            .Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync();
                }

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occoured while filtering employees by string {SearchString} or project {ProjectId}", searchString, ProjectId ?? Guid.Empty);
                return new List<EmployeeVM>();
            }
        }

        public async Task<List<EmployeeVM>> GetEmployeeByProjectId(Guid organizationId, Guid tenantId, Guid? projectId, bool ShowInActive)
        {
            try
            {
                List<Employee> employees = new List<Employee>();
                if (projectId.HasValue)
                {
                    employees = await _context.ProjectAllocations
                        .Include(pa => pa.Employee)
                            .ThenInclude(e => e!.JobRole)
                        .Where(pa => projectId == pa.ProjectId && pa.IsActive && pa.TenantId == tenantId && pa.Employee != null && pa.Employee.IsActive)
                        .Select(pa => pa.Employee!)
                        .Distinct()
                        .ToListAsync();
                }
                else if (ShowInActive)
                {
                    employees = await _context.Employees
                        .Include(fp => fp.JobRole)
                        .Where(c => c.OrganizationId == organizationId && c.IsActive == false)
                        .ToListAsync();
                }
                else
                {
                    employees = await _context.Employees
                        .Include(fp => fp.JobRole)
                        .Where(c => c.OrganizationId == organizationId && c.IsActive == true)
                        .ToListAsync();
                }
                var result = employees.Select(e => _mapper.Map<EmployeeVM>(e)).Distinct().ToList();
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occured while featching list of employee by project ID {ProjectId}", projectId ?? Guid.Empty);
                return new List<EmployeeVM>();
            }
        }
    }
}

