// <copyright file="AuthService.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>

#pragma warning disable CS1591

using System;
using System.Threading.Tasks;
using Jellyfin.Data;
using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace Emby.Server.Implementations.HttpServer.Security
{
    public class AuthService : IAuthService
    {
        private readonly IAuthorizationContext _authorizationContext;
        private readonly ILogger<AuthService> _logger;

        public AuthService(
            IAuthorizationContext authorizationContext,
            ILogger<AuthService> logger)
        {
            _authorizationContext = authorizationContext;
            _logger = logger;
        }

        public async Task<AuthorizationInfo> Authenticate(HttpRequest request)
        {
            var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false);

            if (!auth.HasToken)
            {
                _logger.LogDebug(
                    "Authentication failed: No token provided. Path: {Path}, Client: {Client}, Device: {Device}, DeviceId: {DeviceId}",
                    request.Path,
                    auth.Client ?? "unknown",
                    auth.Device ?? "unknown",
                    auth.DeviceId ?? "unknown");
                return auth;
            }

            if (!auth.IsAuthenticated)
            {
                var tokenPreview = auth.Token?.Length > 8 ? auth.Token.Substring(0, 8) + "..." : auth.Token ?? "null";
                _logger.LogDebug(
                    "Authentication failed: Invalid token. Path: {Path}, Client: {Client}, Device: {Device}, DeviceId: {DeviceId}, Token: {Token}",
                    request.Path,
                    auth.Client ?? "unknown",
                    auth.Device ?? "unknown",
                    auth.DeviceId ?? "unknown",
                    tokenPreview);
                throw new SecurityException("Invalid token.");
            }

            if (auth.User?.HasPermission(PermissionKind.IsDisabled) ?? false)
            {
                _logger.LogWarning(
                    "Authentication failed: User account disabled. User: {User}, Path: {Path}",
                    auth.User.Username,
                    request.Path);
                throw new SecurityException("User account has been disabled.");
            }

            _logger.LogDebug(
                "Authentication successful. User: {User}, Client: {Client}, Device: {Device}, Path: {Path}",
                auth.User?.Username ?? "ApiKey",
                auth.Client ?? "unknown",
                auth.Device ?? "unknown",
                request.Path);

            return auth;
        }
    }
}
