package ru.kayashov.bar.service;

import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import ru.kayashov.bar.controller.dto.VisitorResponseDto;
import ru.kayashov.bar.model.entity.BarEntity;
import ru.kayashov.bar.model.entity.BarIngredientStorage;
import ru.kayashov.bar.model.entity.BarResident;
import ru.kayashov.bar.repository.BarResidentRepository;
import ru.kayashov.bar.model.entity.IngredientEntity;
import ru.kayashov.bar.model.entity.Visitor;
import ru.kayashov.bar.repository.VisitorsRepository;

import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class VisitorService {

    private final VisitorsRepository visitorsRepository;
    private final BarResidentRepository barResidentRepository;

    public Visitor getCurrentVisitor() {
        Long id = ((Visitor) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId();
        return findById(id);
    }

    public Visitor findById(Long id) {
        return visitorsRepository.findById(id).orElseThrow(() -> new RuntimeException("Visitor not found. id: " + id));
    }

    public List<Long> getAllowedIngredients() {
        return getCurrentVisitor().getResidents()
                .stream()
                .filter(BarResident::getActive)
                .map(BarResident::getBar)
                .map(BarEntity::getIngredients)
                .flatMap(List::stream)
                .map(BarIngredientStorage::getIngredient)
                .map(IngredientEntity::getId)
                .toList();
    }

    public List<VisitorResponseDto> findAll() {
        return getCurrentVisitor().getResidents().stream()
                .filter(BarResident::getActive)
                .map(BarResident::getBar)
                .map(BarEntity::getVisitors)
                .flatMap(List::stream)
                .map(this::mapBarResidentToDto)
                .toList();
    }

    private VisitorResponseDto mapBarResidentToDto(BarResident resident) {
        VisitorResponseDto dto = new VisitorResponseDto();
        dto.setId(resident.getVisitor().getId());
        dto.setName(resident.getVisitor().getName());
        dto.setLastName(resident.getVisitor().getLastName());
        dto.setInvited(resident.getInvited());
        dto.setRole(resident.getRole().toString());
        dto.setIsActive(resident.getActive());
        return dto;
    }

    public void invited(Boolean value, Long id) {
        getCurrentVisitor().getResidents()
                .stream()
                .filter(BarResident::getActive)
                .map(BarResident::getBar)
                .map(BarEntity::getVisitors)
                .flatMap(List::stream)
                .filter(v -> Objects.equals(v.getVisitor().getId(), id))
                .peek(v -> v.setInvited(value))
                .forEach(barResidentRepository::save);
    }
}
