package ru.kayashov.bar.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.kayashov.bar.controller.dto.bar.BarResponseDto;
import ru.kayashov.bar.model.entity.BarEntity;
import ru.kayashov.bar.model.entity.CocktailEntity;
import ru.kayashov.bar.model.entity.IngredientEntity;
import ru.kayashov.bar.model.entity.ReceiptEntity;
import ru.kayashov.bar.repository.BarEntityRepository;
import ru.kayashov.bar.repository.CocktailRepository;
import ru.kayashov.bar.repository.IngredientRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Slf4j
@Service
@RequiredArgsConstructor
public class BarService {

    private final BarEntityRepository barEntityRepository;
    private final IngredientRepository ingredientRepository;
    private final CocktailRepository cocktailRepository;

//    @Transactional
    public void changeActiveBar(Long id) {
        Optional<BarEntity> lastBarOpt = barEntityRepository.findByActiveTrue();
        if (lastBarOpt.isPresent()) {
            BarEntity lastBar = lastBarOpt.get();

            lastBar.setActive(false);
            barEntityRepository.save(lastBar);

            lastBar.getIngredients().stream()
                    .peek(i -> i.setIsHave(false))
                    .forEach(ingredientRepository::save);

            cocktailRepository.markAllAsNotAllowed();

            log.info("Бар {} отключен", lastBar.getName());
        }

        BarEntity barEntity = barEntityRepository.findById(id).orElseThrow();
        barEntity.setActive(true);

        List<IngredientEntity> ingredients = barEntity.getIngredients().stream()
                .peek(i -> i.setIsHave(true))
                .map(ingredientRepository::save)
                .toList();

        cocktailRepository.saveAll(findAllowedCocktails(ingredients));

        barEntityRepository.save(barEntity);
        log.info("Бар {} подключен", barEntity.getName());
    }

    public List<BarResponseDto> findAllBar() {
        List<BarEntity> barEntities = barEntityRepository.findAll();
        log.info("По запросу найдено {} баров", barEntities.size());
        return barEntities.stream()
                .map(BarResponseDto::mapToDto)
                .toList();
    }

    public void deleteBar(Long id) {
        barEntityRepository.deleteById(id);
        log.info("Бар с id {} удален", id);
    }

    public BarResponseDto createBar(String name) {
        BarEntity bar = new BarEntity();
        bar.setName(name);
        bar.setActive(false);
        bar = barEntityRepository.save(bar);

        log.info("Создан бар {}", name);

        return BarResponseDto.mapToDto(bar);
    }

    private List<CocktailEntity> findAllowedCocktails(List<IngredientEntity> ingredients) {
        List<CocktailEntity> result = new ArrayList<>();
        for (IngredientEntity ingredient : ingredients) {
            List<CocktailEntity> cocktails = ingredient.getReceipts().stream()
                    .map(ReceiptEntity::getCocktail)
                    .toList();

            for (CocktailEntity cocktail : cocktails) {
                if (cocktail.getReceipt().stream().allMatch(r -> r.getIngredient().getIsHave())) {
                    cocktail.setAllowed(true);
                    result.add(cocktail);
                }
            }
        }
        return result;
    }
}
