package ru.kayashov.bar.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ru.kayashov.bar.bot.domain.methods.AbstractSendMessage;
import ru.kayashov.bar.model.entity.BarEntity;
import ru.kayashov.bar.model.entity.BarResident;
import ru.kayashov.bar.model.entity.CocktailEntity;
import ru.kayashov.bar.model.entity.Pay;
import ru.kayashov.bar.model.entity.SessionEntity;
import ru.kayashov.bar.model.entity.Visitor;
import ru.kayashov.bar.repository.CocktailRepository;
import ru.kayashov.bar.repository.OrdersRepository;
import ru.kayashov.bar.repository.VisitorsRepository;

import java.time.LocalDateTime;
import java.util.List;

import static ru.kayashov.bar.model.entity.OrderStatus.CANCEL;
import static ru.kayashov.bar.model.entity.OrderStatus.DONE;
import static ru.kayashov.bar.model.entity.OrderStatus.NEW;
import static ru.kayashov.bar.model.entity.UserRole.ADMIN;
import static ru.kayashov.bar.model.entity.UserRole.BARMEN;

@Service
@RequiredArgsConstructor
public class OrderService {

    private final VisitorService visitorService;
    private final CocktailRepository cocktailRepository;
    private final OrdersRepository ordersRepository;

    /**
     * Новый заказ
     */
    public List<AbstractSendMessage> createOrder(Long visitorId, Long cocktailId) {
        Visitor visitor = visitorService.findById(visitorId);
        BarEntity bar = visitor.getResidents().stream()
                .filter(BarResident::getActive)
                .map(BarResident::getBar)
                .toList()
                .get(0);
        SessionEntity session = bar.getSessions().stream()
                .filter(SessionEntity::getIsActive)
                .toList()
                .get(0);

        CocktailEntity cocktail = cocktailRepository.findById(cocktailId).orElseThrow();

        Pay pay = new Pay();
        pay.setStatus(NEW);
        pay.setVisitor(visitor);
        pay.setCocktail(cocktail);
        pay.setSession(session);
        pay.setCreatedAt(LocalDateTime.now());
        ordersRepository.save(pay);

        return bar.getVisitors().stream()
                .filter(BarResident::getActive)
                .filter(BarResident::getInvited)
                .filter(b -> b.getRole() == ADMIN || b.getRole() == BARMEN)
                .map(BarResident::getVisitor)
                .map(admin -> createOrderMessage(admin, visitor, cocktail))
                .toList();
    }

    private AbstractSendMessage createOrderMessage(Visitor admin, Visitor client, CocktailEntity cocktail) {
        return AbstractSendMessage.builder()
                .chatId(admin.getId())
                .message(client.getName() + " " + client.getLastName() + " заказал(а) коктейль " + cocktail.getName())
                .build();
    }

    /**
     * Обновить статус заказа
     */
    public AbstractSendMessage updateOrder(boolean check, long l) {
        Pay pay = ordersRepository.findById(l).orElseThrow();
        pay.setStatus(check ? DONE : CANCEL);
        pay.setClosedAt(LocalDateTime.now());
        ordersRepository.save(pay);

        return AbstractSendMessage.builder()
                .chatId(pay.getVisitor().getId())
                .message("Коктейль " + pay.getCocktail().getName() + (check ? " готов" : " отменен"))
                .build();
    }

    /**
     * Получить заказ из очереди
     */
    public List<Pay> getOrders() {
        Visitor visitor = visitorService.getCurrentVisitor();
        return visitor.getResidents().stream()
                .filter(BarResident::getActive)
                .map(BarResident::getBar)
                .map(BarEntity::getSessions)
                .flatMap(List::stream)
                .filter(SessionEntity::getIsActive)
                .map(SessionEntity::getOrders)
                .flatMap(List::stream)
                .toList();
    }
}
