using AutoMapper;
using SportsDivision.Application.DTOs;
using SportsDivision.Application.Interfaces;
using SportsDivision.Domain.Entities;
using SportsDivision.Domain.Enums;
using SportsDivision.Domain.Interfaces;

namespace SportsDivision.Application.Services;

public class EventService : IEventService
{
    private readonly IUnitOfWork _uow;
    private readonly IMapper _mapper;

    public EventService(IUnitOfWork uow, IMapper mapper)
    {
        _uow = uow;
        _mapper = mapper;
    }

    public async Task<IEnumerable<EventDto>> GetAllAsync()
    {
        var events = await _uow.Events.GetAllAsync();
        return _mapper.Map<IEnumerable<EventDto>>(events);
    }

    public async Task<EventDto?> GetByIdAsync(int id)
    {
        var evt = await _uow.Events.GetWithEventLevelsAsync(id);
        return evt == null ? null : _mapper.Map<EventDto>(evt);
    }

    public async Task<IEnumerable<EventDto>> GetByCategoryAsync(EventCategory category)
    {
        var events = await _uow.Events.FindAsync(e => e.Category == category);
        return _mapper.Map<IEnumerable<EventDto>>(events);
    }

    public async Task<EventDto> CreateAsync(EventCreateDto dto)
    {
        var evt = _mapper.Map<Event>(dto);
        if (dto.EventLevelIds.Count > 0)
        {
            foreach (var levelId in dto.EventLevelIds)
            {
                var level = await _uow.EventLevels.GetByIdAsync(levelId);
                if (level != null) evt.EventLevels.Add(level);
            }
        }
        await _uow.Events.AddAsync(evt);
        await _uow.SaveChangesAsync();
        return _mapper.Map<EventDto>(evt);
    }

    public async Task UpdateAsync(EventUpdateDto dto)
    {
        var evt = await _uow.Events.GetWithEventLevelsAsync(dto.EventId)
            ?? throw new KeyNotFoundException("Event not found.");
        _mapper.Map(dto, evt);
        evt.EventLevels.Clear();
        foreach (var levelId in dto.EventLevelIds)
        {
            var level = await _uow.EventLevels.GetByIdAsync(levelId);
            if (level != null) evt.EventLevels.Add(level);
        }
        _uow.Events.Update(evt);
        await _uow.SaveChangesAsync();
    }

    public async Task DeleteAsync(int id)
    {
        var evt = await _uow.Events.GetByIdAsync(id)
            ?? throw new KeyNotFoundException("Event not found.");
        _uow.Events.Remove(evt);
        await _uow.SaveChangesAsync();
    }
}
