package org.fuseri.modulelanguageschool.course;

import org.fuseri.modulelanguageschool.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

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

@Service
public class CourseService {

    private final CourseRepository courseRepository;

    @Autowired
    public CourseService(CourseRepository courseRepository) {
        this.courseRepository = courseRepository;
    }

    @Transactional
    public Course save(Course course) {
        return courseRepository.save(course);
    }

    @Transactional(readOnly = true)
    public Course findById(Long id) {
        return courseRepository.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
                        "Course with id: " + id + " was not found."));
    }

    @Transactional(readOnly = true)
    public Page<Course> findAll(Pageable pageable) {
        return courseRepository.findAll(pageable);
    }

    @Transactional
    public Course update(Long id, Course newCourse) {
        Optional<Course> optionalCourse = courseRepository.findById(id);
        if (optionalCourse.isPresent()) {
            Course course = optionalCourse.get();
            course.setName(newCourse.getName());
            course.setCapacity(newCourse.getCapacity());
            course.setLanguage(newCourse.getLanguage());
            course.setProficiency(newCourse.getProficiency());
            return courseRepository.save(course);
        } else {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND,
                    "Course with id: " + id + " was not found.");
        }
    }

    @Transactional
    public void delete(Long id) {
        courseRepository.deleteById(id);
    }

    @Transactional
    public List<Course> findAll(Language language) {
        return courseRepository.findAllByLang(language);
    }

    @Transactional
    public List<Course> findAll(Language language, ProficiencyLevel proficiencyLevel) {
        return courseRepository.findAllByLangProf(language, proficiencyLevel);
    }

    @Transactional
    public Course enrol(Long id, User student) {
        Optional<Course> optionalCourse = courseRepository.findById(id);
        if (optionalCourse.isPresent()) {
            Course course = optionalCourse.get();
            course.enrolStudent(student);
            return courseRepository.save(course);
        } else {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND,
                    "Course with id: " + id + " was not found.");
        }
    }

    @Transactional
    public Course expel(Long id, User student) {
        Optional<Course> optionalCourse = courseRepository.findById(id);
        if (optionalCourse.isPresent()) {
            Course course = optionalCourse.get();
            course.expelStudent(student);
            return courseRepository.save(course);
        } else {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND,
                    "Course with id: " + id + " was not found.");
        }
    }
}
