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.Employee;
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 System.Net.Mail;

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

    public class UserController : ControllerBase
    {
        private readonly UserHelper _userHelper;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly EmployeeHelper _employeeHelper;
        private readonly ILoggingService _logger;
        private readonly IProjectServices _projectServices;
        private readonly RolesHelper _rolesHelper;
        private readonly Guid tenantId;

        public UserController(EmployeeHelper employeeHelper, UserManager<ApplicationUser> userManager, ILoggingService logger, IProjectServices projectServices, UserHelper userHelper, RolesHelper rolesHelper)
        {
            _userManager = userManager;
            _userHelper = userHelper;
            _logger = logger;
            _employeeHelper = employeeHelper;
            _projectServices = projectServices;
            _rolesHelper = rolesHelper;
            tenantId = userHelper.GetTenantId();
        }

        [HttpGet("profile")]
        public async Task<IActionResult> GetUserProfileFromJwt()
        {
            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));

            }

            var user = await _userHelper.GetCurrentUserAsync();
            Employee emp = new Employee { };
            if (user != null)
            {
                emp = await _employeeHelper.GetEmployeeByApplicationUserID(user.Id);
            }

            List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeId(emp.Id, tenantId);
            string[] projectsId = [];

            /* User with permission manage project  can see all projects */
            if (featurePermission != null && featurePermission.Exists(c => c.Id.ToString() == "172fc9b6-755b-4f62-ab26-55c34a330614"))
            {
                List<Project> projects = await _projectServices.GetAllProjectByTanentID(emp.TenantId ?? Guid.Empty);
                projectsId = projects.Select(c => c.Id.ToString()).ToArray();
            }
            else
            {
                List<ProjectAllocation> allocation = await _projectServices.GetProjectByEmployeeID(emp.Id);
                projectsId = allocation.Select(c => c.ProjectId.ToString()).ToArray();
            }
            EmployeeProfile profile = new EmployeeProfile() { };
            if (featurePermission != null)
            {
                EmployeeVM employeeVM = EmployeeMapper.ToEmployeeVMFromEmployee(emp);
                employeeVM.TenantId = tenantId;

                profile = new EmployeeProfile()
                {
                    EmployeeInfo = employeeVM,
                    Projects = projectsId,
                    FeaturePermissions = featurePermission.Select(c => c.Id.ToString()).Distinct().ToArray(),
                    Features = featurePermission.Select(c => c.FeatureId.ToString()).Distinct().ToArray(),
                };
            }


            return Ok(ApiResponse<object>.SuccessResponse(profile, "Success", 200));
        }

        [HttpGet("email/{email}")]
        public async Task<IActionResult> GetUserByEmail(string email)
        {
            var isvalid = IsValidEmail(email);
            if (!isvalid)
            {
                _logger.LogWarning("User provided invalid email address");
                return BadRequest(ApiResponse<object>.ErrorResponse("Invalid email", "Invalid email", 400));
            }
            var user = await _userManager.FindByEmailAsync(email);

            if (user == null)
            {
                _logger.LogInfo("User with email {Email} not found in ASP.NET users table", email);
                return Ok(ApiResponse<object>.SuccessResponse(true, "User not exists", 200));
            }
            else
            {
                _logger.LogInfo("User with email {Email} founded in ASP.NET users table", email);
                return Ok(ApiResponse<object>.SuccessResponse(false, "User exists", 200));
            }

        }

        private static bool IsValidEmail(string email)
        {
            if (string.IsNullOrWhiteSpace(email))
                return false;
            try
            {
                var addr = new MailAddress(email);
                return addr.Address == email.Trim();
            }
            catch
            {
                return false;
            }
        }
    }
}
