using JobPortalAPI.Configurations;
using JobPortalAPI.DTOs;
using JobPortalAPI.Models;
using JobPortalAPI.UnitOfWork;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.Formats.Asn1;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace JobPortalAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AccountController : BaseController
    {
        private readonly UserManager<IdentityUser> _userManager;
        private readonly IConfiguration _configuration;
        public AccountController(UserManager<IdentityUser> userManager, IConfiguration configuration, IUnitOfWork unitOfWork) : base(unitOfWork)

        {
            _userManager = userManager;
            _configuration = configuration;

        }
        [AllowAnonymous]
        [HttpPost("JobseekerLogIn")]
        public async Task<IActionResult> JobseekerLogIn([FromBody] LogInDto dto)
        {
            if (ModelState.IsValid)
            {
                var user_exist = await _userManager.FindByEmailAsync(dto.email);
                if (user_exist == null)
                {
                    return BadRequest
                    (
                         new AuthResult()
                         {
                             result = false,
                             Errors = new List<string>()
                            {
                                "Email doesn't exist"
                            }

                         }
                    );
                }
                var is_correct = await _userManager.CheckPasswordAsync( user_exist, dto.password);
                if(!is_correct)
                {
                    return BadRequest
                    (
                         new AuthResult()
                         {
                             result = false,
                             Errors = new List<string>()
                             {
                                "password and email do not match!!"
                             }
                         }
                    );
                }
                string token = GenerateJwtToken( user_exist);
                var person = _unitOfWork.PersonRepo.GetAll().FirstOrDefault(p => p.Email == dto.email);
                var jobseeker = _unitOfWork.JobSeekerRepo.GetAll().FirstOrDefault(p => p.Id == person!.Id);

                 if(jobseeker != null)
                 {
                    return Ok(new AuthResult()
                    {
                        Id = person!.Id,
                        result = true,
                        Token = token,
                        isCompany = false
                    }) ; 
                 }
                 else
                {
                    return BadRequest(new AuthResult()
                    {
                        result = false,
                        Errors = new List<string>()
                        {
                            "This email for company and you are try to login as jobseeker!!!"
                        }

                    });
                }


            }
            return BadRequest(new AuthResult()
            {
                result = false,
                Errors = new List<string>()
                        {
                            "Invalid payload"
                        }

            });
        }
        [AllowAnonymous]
        [HttpPost("CompanyLogIn")]
        public async Task<IActionResult> CompanyLogIn([FromBody] LogInDto dto)
        {
            if (ModelState.IsValid)
            {
                var user_exist = await _userManager.FindByEmailAsync(dto.email);
                if (user_exist == null)
                {
                    return BadRequest
                    (
                         new AuthResult()
                         {
                             result = false,
                             Errors = new List<string>()
                            {
                                "Email doesn't exist"
                            }

                         }
                    );
                }
                var is_correct = await _userManager.CheckPasswordAsync(user_exist, dto.password);
                if (!is_correct)
                {
                    return BadRequest
                    (
                         new AuthResult()
                         {
                             result = false,
                             Errors = new List<string>()
                             {
                                "password and email do not match!!"
                             }
                         }
                    );
                }
                string token = GenerateJwtToken(user_exist);
                var person = _unitOfWork.PersonRepo.GetAll().FirstOrDefault(p => p.Email == dto.email);
                var company = _unitOfWork.CompanyRepo.GetAll().FirstOrDefault(p => p.Id == person!.Id);

                if (company != null)
                {
                    return Ok(new AuthResult()
                    {
                        Id = person!.Id,
                        result = true,
                        Token = token,
                        isCompany = true

                    }); ;
                }
                else
                {
                    return BadRequest(new AuthResult()
                    {
                        result = false,
                        Errors = new List<string>()
                        {
                            "This email for jobseeker and you are try to login as company!!!"
                        }

                    });
                }


            }
            return BadRequest(new AuthResult()
            {
                result = false,
                Errors = new List<string>()
                        {
                            "Invalid payload"
                        }

            });
        }
        [HttpPut("ChangePassword/{id}")]
        public async Task<IActionResult> ChangePassword(int id ,[FromBody] ChangePasswordDto dto)
        {
            if (ModelState.IsValid)
            {
                var person = _unitOfWork.PersonRepo.Get(id);
                var user_exist = await _userManager.FindByEmailAsync(dto.email);
                if (user_exist != null)
                {
                    if(dto.newPassword == dto.confirmedPassword)
                    {

                        if (user_exist.Email == person.Email)
                        {
                            var is_correct = await _userManager.CheckPasswordAsync(user_exist, dto.oldPassword);
                            if (is_correct)
                            {
                                await _userManager.ChangePasswordAsync(user_exist, dto.oldPassword, dto.newPassword);

                                return Ok();

                            }
                            else
                            {
                                return BadRequest(
                                     new AuthResult()
                                     {
                                         Errors = new List<string>()
                                         {
                                       "Email and password does not match"
                                         }
                                     }
                                    );
                            }

                        }
                        else
                        {
                            return BadRequest(
                                 new AuthResult()
                                 {
                                     Errors = new List<string>()
                                         {
                                       "this email is not for you"
                                         }
                                 }
                                );
                        }

                    }
                    else
                    {
                        return BadRequest(
                             new AuthResult()
                             {
                                 Errors = new List<string>()
                                     {
                                       "new password and confirmed password do not match!!! "
                                     }
                             }
                            );
                    }
                }
                else
                {
                    return NotFound(
                        new AuthResult()
                        {
                            Errors = new List<string>()
                                     {
                                       "this email does not found "
                                     }
                        }
                        );
                }
            }
            else
            {
                return BadRequest(
                    new AuthResult()
                     {
                          Errors = new List<string>()
                            {
                               "Enter valid values"
                            }
                    }











                    );
            }
               
        }

        private String GenerateJwtToken(IdentityUser user)
        {
            var jwtTokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(_configuration.GetSection("JwtConfig:Secret").Value);
            var TokenDescriptor = new SecurityTokenDescriptor()
            {
                Subject = new ClaimsIdentity(new[]
                {
                    new Claim("Id",user.Id),
                    new Claim(JwtRegisteredClaimNames.Sub,user.Email),
                    new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),
                    new Claim(JwtRegisteredClaimNames.Iat,DateTime.Now.ToUniversalTime().ToString()),


                }),
                Expires = DateTime.Now.AddHours(1),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),SecurityAlgorithms.HmacSha256),
            };
            var token = jwtTokenHandler.CreateToken(TokenDescriptor);
            var jwtToken = jwtTokenHandler.WriteToken(token);
            return jwtToken;
        }


    }
}
