using AutoMapper;
using DigitalData.Core.Abstraction.Application;
using DigitalData.Core.Abstraction.Application.DTO;
using DigitalData.Core.Abstraction.Application.Repository;

namespace DigitalData.Core.Application;

/// <summary>
/// Provides generic Read (Read and Delete) operations for a specified type of entity.
/// </summary>
/// <typeparam name="TReadDto">The DTO type for read operations.</typeparam>
/// <typeparam name="TEntity">The entity type.</typeparam>
/// <typeparam name="TId">The type of the identifier for the entity.</typeparam>
[Obsolete("Use MediatR")]
public class ReadService<TCRUDRepository, TReadDto, TEntity, TId> : IReadService<TReadDto, TEntity, TId>
    where TCRUDRepository : ICRUDRepository<TEntity, TId> where TReadDto : class where TEntity : class
{
    protected readonly TCRUDRepository _repository;
    protected readonly IMapper _mapper;

    /// <summary>
    /// Initializes a new instance of the CRUDService class with the specified repository, translation service, and mapper.
    /// </summary>
    /// <param name="repository">The CRUD repository for accessing the database.</param>
    /// <param name="mapper">The AutoMapper instance for mapping between DTOs and entity objects.</param>
    public ReadService(TCRUDRepository repository, IMapper mapper)
    {
        _repository = repository;
        _mapper = mapper;
    }

    /// <summary>
    /// Asynchronously reads an entity by its identifier and maps it to a read DTO.
    /// </summary>
    /// <param name="id">The identifier of the entity to read.</param>
    /// <returns>A service result indicating success or failure, including the read DTO if successful.</returns>
    public virtual async Task<DataResult<TReadDto>> ReadByIdAsync(TId id)
    {
        var entity = await _repository.ReadByIdAsync(id);
        return entity is null
            ? Result.Fail<TReadDto>()
            : Result.Success(_mapper.Map<TReadDto>(entity));
    }

    /// <summary>
    /// Asynchronously reads all entities and maps them to read DTOs.
    /// </summary>
    /// <returns>A service result including a collection of read DTOs.</returns>
    public virtual async Task<DataResult<IEnumerable<TReadDto>>> ReadAllAsync()
    {
        var entities = await _repository.ReadAllAsync();
        var readDto = _mapper.Map<IEnumerable<TReadDto>>(entities);
        return Result.Success(readDto);
    }

    /// <summary>
    /// Asynchronously deletes an entity by its identifier.
    /// </summary>
    /// <param name="id">The identifier of the entity to delete.</param>
    /// <returns>A service message indicating success or failure.</returns>
    public virtual async Task<Result> DeleteAsyncById(TId id)
    {
        TEntity? entity = await _repository.ReadByIdAsync(id);

        if (entity is null)
            return Result.Fail();

        bool isDeleted = await _repository.DeleteAsync(entity);
        return isDeleted ? Result.Success() : Result.Fail();
    }

    /// <summary>
    /// Asynchronously checks if an entity with the specified identifier exists.
    /// </summary>
    /// <param name="id">The identifier of the entity to check.</param>
    /// <returns>A Task that represents the asynchronous operation. The task result contains a boolean value indicating whether the entity exists.</returns>
    public virtual async Task<bool> HasEntity(TId id) => await _repository.CountAsync(id) > 0;
}