package ru.kayashov.bar.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ru.kayashov.bar.bot.domain.Bot;
import ru.kayashov.bar.bot.domain.methods.AbstractSendMessage;
import ru.kayashov.bar.controller.dto.OrderResponseDto;
import ru.kayashov.bar.model.entity.BarEntity;
import ru.kayashov.bar.model.entity.BarResident;
import ru.kayashov.bar.model.entity.SessionEntity;
import ru.kayashov.bar.model.entity.Visitor;
import ru.kayashov.bar.service.OrderService;
import ru.kayashov.bar.service.VisitorService;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;

@Slf4j
@CrossOrigin(origins = {"*"})
@RestController
@RequestMapping("/api/order")
@RequiredArgsConstructor
public class OrderController {

    private final ExecutorService executor;
    private final OrderService orderService;
    private final Bot bot;
    private final VisitorService visitorService;

    @PostMapping
    public void pay(@RequestParam Long cocktail) {
        Long id = ((Visitor) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId();
        List<AbstractSendMessage> messages = orderService.createOrder(id, cocktail);
        executor.submit(() -> messages.forEach(bot::sendMessage));
    }

    @DeleteMapping
    public void cancelOrder(@RequestParam Long id) {
        AbstractSendMessage message = orderService.updateOrder(false, id);
        executor.submit(() -> bot.sendMessage(message));
    }

    @PutMapping
    public void doneOrder(@RequestParam Long id) {
        AbstractSendMessage message = orderService.updateOrder(true, id);
        executor.submit(() -> bot.sendMessage(message));
    }

    @GetMapping
    public List<OrderResponseDto> getOrders() {
        return orderService.getOrders()
                .stream()
                .map(OrderResponseDto::new)
                .toList();
    }

    @GetMapping("/my")
    public List<OrderResponseDto> getMyOrders() {
        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)
                .filter(o -> Objects.equals(o.getVisitor().getId(), visitor.getId()))
                .map(OrderResponseDto::new)
                .toList();
    }
}
