using Asp.Versioning;
using Core.Thalos.Adapters;
using Core.Thalos.Adapters.Common.Constants;
using Core.Thalos.Adapters.Contracts;
using Core.Thalos.Application.UseCases.Users.Input;
using Core.Thalos.External.Clients.Thalos.Requests.Users;
using LSA.Dashboard.External.Clients.Dashboard;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Core.Thalos.BFF.Api.Controllers
{
    /// 
    /// Handles all requests for Authentication.
    /// 
    [ApiVersion(MimeTypes.ApplicationVersion)]
    [Route("api/v{api-version:apiVersion}/[controller]")]
    [Produces(MimeTypes.ApplicationJson)]
    [Consumes(MimeTypes.ApplicationJson)]
    [ApiController]
    public class AuthenticationController(IThalosServiceClient thalosServiceClient, ILogger logger, ITokenService tokenService) : BaseController(logger)
    {
        /// 
        /// Get token for user.
        /// 
        /// A  representing
        /// the asynchronous execution of the service.
        /// The Token was generated.
        /// The service internal error.
        [HttpGet]
        [Route(Routes.GenerateToken)]
        [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
        [Authorize(AuthenticationSchemes = Schemes.AzureScheme)]
        public async Task GenerateTokenService(CancellationToken cancellationToken)
        {
            try
            {
                logger.LogInformation($"{nameof(GenerateTokenService)} - Request received - Payload: {null}");
                var tokenAdapter = new TokenAdapter();
                var email = tokenService.GetEmailClaim(this.HttpContext);
                if (string.IsNullOrEmpty(email)) return BadRequest("An error ocurred while desearializing the token");
                var tokenResult = await Handle(() => thalosServiceClient.GetTokenAdapterService(new GetTokenAdapterRequest { Email = email }, cancellationToken)).ConfigureAwait(false);
                if (tokenResult is ObjectResult tokenOkResult && tokenOkResult.StatusCode == 200)
                    tokenAdapter = tokenOkResult.Value as TokenAdapter;
                else
                    return tokenResult;
                if (tokenAdapter is not null && tokenAdapter.User is not null)
                {
                    var (token, modules) = tokenService.GenerateAccessToken(tokenAdapter);
                    await Handle(() => thalosServiceClient.LoginUserService(new LoginUserRequest { Email = email }, cancellationToken)).ConfigureAwait(false);
                    return Ok(new { token, modules });
                }
                else
                {
                    return BadRequest("An error ocurred");
                }
            }
            catch (Exception ex)
            {
                logger.LogError($"{nameof(GenerateTokenService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload : {null}");
                throw;
            }
        }
        /// 
        /// Refreshes the custom access token.
        /// 
        /// A  representing
        /// the asynchronous execution of the service.
        /// The user with it's new token.
        /// The service internal error.
        [HttpGet]
        [Route(Routes.RefreshToken)]
        [ProducesResponseType(typeof(UserAdapter), StatusCodes.Status200OK)]
        //[Authorize(AuthenticationSchemes = Schemes.DefaultScheme)]
        public async Task RefreshCustomTokenAsync(CancellationToken cancellationToken)
        {
            var tokenAdapter = new TokenAdapter();
            var email = tokenService.GetEmailClaim(this.HttpContext);
            var tokenResult = await Handle(() => thalosServiceClient.GetTokenAdapterService(new GetTokenAdapterRequest { Email = email }, cancellationToken)).ConfigureAwait(false);
            if (tokenResult is ObjectResult tokenOkResult && tokenOkResult.StatusCode == 200)
            {
                tokenAdapter = tokenOkResult.Value as TokenAdapter;
                if (tokenAdapter != null)
                {
                    var result = tokenService.RefreshAccessToken(HttpContext, tokenAdapter);
                    return result;
                }
            }
            else return tokenResult;
            return new UnauthorizedObjectResult("Error in refreshToken");
        }
    }
}