using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authorization.Identity;
using MediatR;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.WebUtilities;
using System.Text;

namespace Indotalent.Features.Account.Register.Cqrs;

public class CreateUserRequest
{
    public string FullName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string Password { get; set; } = string.Empty;
    public bool IsActive { get; set; } = true;
    public bool EmailConfirmed { get; set; } = false;
}

public class CreateUserResponse
{
    public string? Id { get; set; }
    public string? Email { get; set; }
}

public record CreateUserCommand(CreateUserRequest Data) : IRequest<CreateUserResponse>;

public class RegisterHandler : IRequestHandler<CreateUserCommand, CreateUserResponse>
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IEmailSender<ApplicationUser> _emailSender;
    private readonly IConfiguration _configuration;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public RegisterHandler(
        UserManager<ApplicationUser> userManager,
        IEmailSender<ApplicationUser> emailSender,
        IConfiguration configuration,
        IHttpContextAccessor httpContextAccessor)
    {
        _userManager = userManager;
        _emailSender = emailSender;
        _configuration = configuration;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<CreateUserResponse> Handle(CreateUserCommand request, CancellationToken cancellationToken)
    {
        var user = new ApplicationUser
        {
            UserName = request.Data.Email,
            Email = request.Data.Email,
            FullName = request.Data.FullName,
            IsActive = request.Data.IsActive,
            EmailConfirmed = request.Data.EmailConfirmed,
        };

        var result = await _userManager.CreateAsync(user, request.Data.Password);

        if (!result.Succeeded)
        {
            var errors = result.Errors.Select(x => x.Description).ToList();
            throw new Exception(string.Join(", ", errors));
        }

        var rolesToAdd = ApplicationRoles.AllRoles
            .Where(role => role != ApplicationRoles.Admin)
            .ToList();

        if (rolesToAdd.Any())
        {
            await _userManager.AddToRolesAsync(user, rolesToAdd);
        }

        var requireConfirmation = _configuration.GetValue<bool>("IdentitySettings:SignIn:RequireConfirmedAccount");

        if (requireConfirmation)
        {
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));

            var requestHttp = _httpContextAccessor.HttpContext?.Request;
            var scheme = requestHttp?.Scheme ?? "https";
            var host = requestHttp?.Host.Value ?? "localhost:8080";

            var callbackUrl = $"{scheme}://{host}/account/confirm-email?userId={user.Id}&code={code}";

            var message = $@"
                <div style=""font-family: Arial, sans-serif;"">
                    <h3>Welcome, {user.FullName}!</h3>
                    <p>Please confirm your account by clicking the link below:</p>
                    <p><a href=""{callbackUrl}"" style=""color: #2196F3; font-weight: bold; text-decoration: underline;"">Confirm Account</a></p>
                    <br/>
                    <p style=""font-size: 0.8em; color: #666;"">If the link doesn't work, copy and paste this URL into your browser:</p>
                    <p style=""font-size: 0.8em; color: #666;"">{callbackUrl}</p>
                </div>";

            await _emailSender.SendConfirmationLinkAsync(user, user.Email!, message);
        }

        return new CreateUserResponse
        {
            Id = user.Id,
            Email = user.Email
        };
    }
}