package ru.soune.nocopy.service.tariff;

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.soune.nocopy.dto.tarriff.TariffDTO;
import ru.soune.nocopy.entity.tarif.Tariff;
import ru.soune.nocopy.entity.tarif.TariffTimeTerm;
import ru.soune.nocopy.entity.tarif.TariffType;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.exception.TariffNotFoundException;
import ru.soune.nocopy.repository.TariffRepository;

import java.util.List;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class TariffService {

    private final TariffRepository tariffRepository;

    public void addTariff(String tariffName, double price, String type, int tokens, long diskSize, long maxUsers,
                          int maxFilesCount, String tariffTerm) {
        Tariff tariff = new Tariff();
        tariff.setName(tariffName);
        tariff.setPrice(price);
        tariff.setType(type);
        tariff.setTokens(tokens);
        tariff.setDiskSize(diskSize);
        tariff.setMaxUsers(maxUsers);
        tariff.setMaxFilesCount(maxFilesCount);
        tariff.setTariffTerm(TariffTimeTerm.valueOf(tariffTerm.toUpperCase()));

        tariffRepository.save(tariff);
    }

    public List<TariffDTO> getTariffByAccountType(User user) {
        String typeAccount = user.canManageCompanySettings() ? "b2b": "b2c";

        return tariffRepository.findByTariffAccountType(typeAccount)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<TariffDTO> getTariffByAccountTypeAndTariffTerm(User user, TariffTimeTerm tariffTerm) {
        String typeAccount = user.canManageCompanySettings() ? "b2b": "b2c";

        return tariffRepository.findByTariffAccountTypeAndTariffTerm(typeAccount, tariffTerm)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<TariffDTO> getTariffByType(String type) {
        return tariffRepository.findByTariffAccountType(type)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<TariffDTO> getAllTariffs() {
        return tariffRepository.findAllByOrderByPriceAsc()
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public TariffDTO getTariffById(Long id) {
        return tariffRepository.findById(id)
                .map(this::convertToDTO)
                .orElseThrow(() ->  new TariffNotFoundException("Tariff not found"));
    }

    public TariffDTO getTariffByType(TariffType type) {
        return tariffRepository.findByType(type.toString())
                .map(this::convertToDTO)
                .orElseThrow(() ->  new TariffNotFoundException("Tariff not found"));
    }

    @Transactional
    public TariffDTO createTariff(TariffDTO tariffDTO) {
        Tariff tariff = new Tariff();
        updateTariffFromDTO(tariff, tariffDTO);

        return convertToDTO(tariffRepository.save(tariff));
    }

    @Transactional
    public TariffDTO updateTariff(Long id, TariffDTO tariffDTO) {
        Tariff tariff = tariffRepository.findById(id)
                .orElseThrow(() -> new TariffNotFoundException("Tariff not found"));
        updateTariffFromDTO(tariff, tariffDTO);

        return convertToDTO(tariffRepository.save(tariff));
    }

    @Transactional
    public void deleteTariff(Long id) {
        tariffRepository.deleteById(id);
    }

    private TariffDTO convertToDTO(Tariff tariff) {
        TariffTimeTerm tariffTerm = tariff.getTariffTerm();

        return new TariffDTO(
                tariff.getId(),
                tariff.getType(),
                tariff.getName(),
                tariff.getPrice(),
                tariff.getTokens(),
                tariff.getMaxFilesCount(),
                tariff.getDiskSize(),
                tariff.getMaxUsers(),
                tariffTerm == null ? "" : tariffTerm.name()
        );
    }

    private void updateTariffFromDTO(Tariff tariff, TariffDTO dto) {
        tariff.setType(dto.getType());
        tariff.setName(dto.getName());
        tariff.setPrice(dto.getPrice());
        tariff.setTokens(dto.getTokens());
        tariff.setMaxFilesCount(dto.getMaxFilesCount());
        tariff.setDiskSize(dto.getDiskSize());
        tariff.setMaxUsers(dto.getMaxUsers());
        tariff.setTariffTerm(TariffTimeTerm.valueOf(dto.getTariffTerm().toUpperCase()));
    }
}
