using DigitalData.Core.API;
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.Base;
using DigitalData.UserManager.Application.DTOs.User;
using DigitalData.UserManager.Domain.Entities;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;

namespace DigitalData.UserManager.API.Controllers
{
    [Authorize]
    public class BaseAuthController<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TBaseEntity> : CRUDControllerBaseWithErrorHandling<TCRUDService, TCreateDto, TReadDto, TUpdateDto, TBaseEntity, int>
        where TCRUDService : IBaseService<TCreateDto, TReadDto, TUpdateDto, TBaseEntity>
        where TCreateDto : BaseCreateDto
        where TReadDto : class
        where TUpdateDto : BaseUpdateDto
        where TBaseEntity : BaseEntity
    {
        private readonly Lazy<int?> _lUserId;

        public BaseAuthController(ILogger logger, TCRUDService service, IUserService userService) : base(logger, service)
        {
            _lUserId = new(() =>
            {
                var idSt = User.FindFirstValue(ClaimTypes.NameIdentifier);
                bool hasId = int.TryParse(idSt, out int id);
                return hasId ? id : null;
            });

            service.UserFactoryAsync = async () =>
            {
                var id = _lUserId.Value;

                return id is int intId
                    ? await userService.ReadByIdAsync(intId).ThenAsync(
                        Success: res => res,
                        Fail: UserReadDto? (m, n) =>
                        {
                            _logger.LogNotice(n);
                            return null;
                        })
                    : null;
            };
        }
    }
}