using Netina.Common.Models.Api;
using Netina.Common.Models.Exception;
using Netina.Domain.CommandQueries.Commands;
using Netina.Domain.CommandQueries.Queries;
using Netina.Domain.Entities.Orders;
using Netina.Domain.Entities.Users;
using Netina.Domain.Enums;
using Netina.Repository.Abstracts;
using Netina.Repository.Repositories.Base.Contracts;

namespace Netina.Core.EntityServices.OrderBagHandlers;

public class GetUserOrderBagQueryHandler : IRequestHandler<GetUserOrderBagQuery,Order>
{
    private readonly IRepositoryWrapper _repositoryWrapper;
    private readonly ICurrentUserService _currentUserService;
    private readonly IMediator _mediator;

    public GetUserOrderBagQueryHandler(IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService,IMediator mediator)
    {
        _repositoryWrapper = repositoryWrapper;
        _currentUserService = currentUserService;
        _mediator = mediator;
    }
    public async Task<Order> Handle(GetUserOrderBagQuery request, CancellationToken cancellationToken)
    {
        if (_currentUserService.UserId == null)
            throw new AppException("Customer id notfound", ApiResultStatusCode.BadRequest);
        if (!Guid.TryParse(_currentUserService.UserId, out Guid userId))
            throw new AppException("Customer id wrong",ApiResultStatusCode.BadRequest);

        var customer = await _repositoryWrapper.SetRepository<Customer>()
            .TableNoTracking
            .FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken);
        if (customer == null)
        {
            customer = new Customer
            {
                UserId = userId
            };
            _repositoryWrapper.SetRepository<Customer>()
                .Add(customer);
            await _repositoryWrapper.SaveChangesAsync(cancellationToken);
        }

        var order = await _repositoryWrapper.SetRepository<Order>()
            .TableNoTracking
            .FirstOrDefaultAsync(o => o.CustomerId == customer.Id && o.OrderStatus == OrderStatus.OrderBag,cancellationToken);
        
        if (order == null)
            order = await _mediator.Send(new CreateBaseOrderCommand(userId),cancellationToken);
        else
        {
            var orderProducts = await _repositoryWrapper.SetRepository<OrderProduct>()
                .TableNoTracking
                .Where(op=>op.OrderId==order.Id)
                .ToListAsync(cancellationToken);

            orderProducts.ForEach(op=>order.AddOrderProduct(op));
        }

        return order;
    }
}