package org.fuseri.modulelanguageschool.user;

import org.fuseri.model.dto.course.CourseDto;
import org.fuseri.model.dto.user.UserAddLanguageDto;
import org.fuseri.model.dto.user.UserCreateDto;
import org.fuseri.model.dto.user.UserDto;
import org.fuseri.modulelanguageschool.common.DomainService;
import org.fuseri.modulelanguageschool.course.CourseMapper;
import org.fuseri.modulelanguageschool.course.Language;
import org.fuseri.modulelanguageschool.course.ProficiencyLevel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Transactional
public class UserFacade {

    private final UserMapper mapper;
    private final CourseMapper courseMapper;
    private final UserService service;

    @Autowired
    public UserFacade(UserMapper mapper, CourseMapper courseMapper, UserService service) {
        this.mapper = mapper;
        this.courseMapper = courseMapper;
        this.service = service;
    }

    @Cacheable(cacheNames = "user")
    public UserDto find(Long id) {
        return mapper.toDto(service.find(id));
    }

    public UserDto register(UserCreateDto dto) {
        Optional<User> optionalUser = service.findUserByEmail(dto.getEmail());
        if (optionalUser.isPresent()) {
            return mapper.toDto(optionalUser.get());
        }
        var user = mapper.fromCreateDto(dto);
        return mapper.toDto(service.create(user));
    }

    public UserDto create(UserCreateDto dto) {
        var user = mapper.fromCreateDto(dto);
        return mapper.toDto(service.create(user));
    }

    public void delete(Long id) {
        service.delete(id);
    }

    public UserDto update(Long id, UserCreateDto dto) {
        var user = mapper.fromCreateDto(dto);
        var result = service.update(id, user);
        return mapper.toDto(result);

    }

    public Page<UserDto> findAll(int page) {
        PageRequest pageRequest = PageRequest.of(page, DomainService.DEFAULT_PAGE_SIZE);
        return mapper.toDtoPage(service.findAll(pageRequest));
    }

    public UserDto addLanguageProficiency(Long id, UserAddLanguageDto body) {
        var language = Language.valueOf(body.getLanguage().name());
        var proficiency = ProficiencyLevel.valueOf(body.getProficiency().name());
        User user = service.addLanguageProficiency(id, language, proficiency);
        return mapper.toDto(user);
    }

    public List<CourseDto> getEnrolled(Long id) {
        return courseMapper.mapToList(service.getEnrolled(id));
    }

    public List<CourseDto> getFinished(Long id) {
        return courseMapper.mapToList(service.getFinished(id));
    }

}
