package premium_store.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import premium_store.model.TankLevel;
import premium_store.repository.TankLevelRepository;
import premium_store.service.exception.LevelNotFoundException;
import premium_store.util.validation.ValidatorUtil;

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

//сервис после удаления EntityManager и добавления нашего репозитория. То есть у него уже все методы работы с полями прописаны за нас?
@Service
public class TankLevelService {
    private final TankLevelRepository tankLevelRepository;
    private final ValidatorUtil validatorUtil;

    public TankLevelService(TankLevelRepository tankLevelRepository, ValidatorUtil validatorUtil){
        this.tankLevelRepository = tankLevelRepository;
        this.validatorUtil = validatorUtil;
    }

    @Transactional
    public TankLevel addLevel(int newLevel) {
        final TankLevel tankLevel = new TankLevel(newLevel);
        validatorUtil.validate(tankLevel);

        return tankLevelRepository.save(tankLevel);
    }

    //здесь используем Optional - спец. тип данных, позволяющий определять, вернулось ли что-то при вызове метода, или вернулся null
    @Transactional(readOnly = true)
    public TankLevel findLevel(Long id) {
        final Optional<TankLevel> level = tankLevelRepository.findById(id);

        //благодаря Optional можем вызвать orElseThrow, который в случае null сделает проброс кастомного исключения
        return level.orElseThrow(() -> new LevelNotFoundException(id));
    }

    @Transactional(readOnly = true)
    public List<TankLevel> findAllLevels() {
        return tankLevelRepository.findAll();
    }

    @Transactional
    public TankLevel updateLevel(Long id, int newLevel) {
        final TankLevel currentTankLevel = findLevel(id);
        currentTankLevel.setLevel(newLevel);
        validatorUtil.validate(currentTankLevel);

        return tankLevelRepository.save(currentTankLevel);
    }

    @Transactional
    public TankLevel deleteLevel(Long id) {
        final TankLevel currentTankLevel = findLevel(id);
        tankLevelRepository.delete(currentTankLevel);

        return currentTankLevel;
    }

    @Transactional
    public void deleteAllLevels() {
        tankLevelRepository.deleteAll();
    }
}

