using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Yuna.Website.Server.Infrastructure;
using System.Text.Json.Serialization;
using Yuna.Website.Server.Services.TokenService;
using Yuna.Website.Server.Model;
using Yuna.Website.Server.Services.UserService;
using Yuna.Website.Server.API.DTO;

namespace Yuna.Website.Server.API
{
    public class AuthEndpoints
    {
        public void Define(WebApplication app)
        {
            app.MapPost("/api/auth/login", Login)
            .WithTags("auth")
            .Produces(200)
            .Produces(401)
            .Produces(400);

            app.MapPost("/api/user/register", RegisterUser)
            .WithTags("auth")
            .Produces(200)
            .Produces(400);

        }

        
        public async Task<IResult> Login(HttpContext context, [FromBody] LoginRequest request, IUserService userService, ITokenService tokenService)
        {
            var userFromDb = await userService.GetByUsername(request.UserName);
            if (userFromDb is null) return Results.Unauthorized();

            var hashedPassword = Encrypter.HashPassword(request.RawPassword, request.UserName);
            if (!hashedPassword.Equals(userFromDb.HashedPassword)) return Results.Unauthorized();
            await SetAccessToken(context, tokenService, userFromDb);
            return Results.Ok("");
        }


        private static async Task SetAccessToken(HttpContext context, ITokenService tokenService, User userFromDb)
        {
            var identity = tokenService.CreateAccessToken(userFromDb);

            await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
        }

        private static void SetFrontendCookie(User user, HttpContext context)
        {
            context.SaveToCookies("user", new CookieUserModel(user));
        }

        public class RegisterUserRequest
        {
            public string username { get; set; } = null!;
            public string password { get; set; } = null!;
            public string referalCode { get; set; } = null!;
        }

        public async Task<IResult> RegisterUser([FromBody] RegisterUserRequest dto, IUserService userService)
        {

            if (!dto.referalCode.Equals(Settings.ReferalCode)) return Results.BadRequest();

            var hashedPassword = Encrypter.HashPassword(dto.password, dto.username);

            var userToRegister = new User(dto.username, hashedPassword);

            var result = await userService.Create(userToRegister);
            if (result is null) return Results.BadRequest();

            return Results.Ok();
        }
    }
}