content: package com.nonononoki.alovoa.service;
  
  import com.fasterxml.jackson.databind.ObjectMapper;
  import com.nonononoki.alovoa.Tools;
  import com.nonononoki.alovoa.component.TextEncryptorConverter;
  import com.nonononoki.alovoa.entity.User;
  import com.nonononoki.alovoa.entity.user.UserDonation;
  import com.nonononoki.alovoa.model.AlovoaException;
  import com.nonononoki.alovoa.model.DonationBmac;
  import com.nonononoki.alovoa.model.DonationDto;
  import com.nonononoki.alovoa.model.DonationKofi;
  import com.nonononoki.alovoa.repo.UserDonationRepository;
  import com.nonononoki.alovoa.repo.UserRepository;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.beans.factory.annotation.Value;
  import org.springframework.stereotype.Service;
  
  import javax.crypto.BadPaddingException;
  import javax.crypto.IllegalBlockSizeException;
  import javax.crypto.NoSuchPaddingException;
  import java.io.UnsupportedEncodingException;
  import java.net.MalformedURLException;
  import java.net.UnknownHostException;
  import java.security.InvalidAlgorithmParameterException;
  import java.security.InvalidKeyException;
  import java.security.NoSuchAlgorithmException;
  import java.util.Date;
  import java.util.List;
  
  @Service
  public class DonateService {
  
      private static final int FILTER_RECENT = 1;
      private static final int FILTER_AMOUNT = 2;
      private static final Logger logger = LoggerFactory.getLogger(DonateService.class);
      private static final String KOFI_TEST_TRANSACTION_ID = "1234-1234-1234-1234";
      private static final String KOFI_TEST_EMAIL = "john@example.com";
      private static final String BMAC_TEST_EMAIL = "test@example.com";
      @Autowired
      private UserDonationRepository userDonationRepo;
      @Autowired
      private UserRepository userRepo;
      @Autowired
      private AuthService authService;
      @Autowired
      private UserService userService;
      @Autowired
      private ObjectMapper objectMapper;
      @Autowired
      private TextEncryptorConverter textEncryptor;
      @Value("${app.donate.users.max}")
      private int maxEntries;
      @Value("${spring.profiles.active}")
      private String profile;
      @Value("${app.donate.kofi.key}")
      private String kofiKey;
      @Value("${app.donate.bmac.key}")
      private String bmacKey;
  
      @Value("${app.search.ignore-intention}")
      private boolean ignoreIntention;
  
      public List<DonationDto> filter(int filter) throws AlovoaException, InvalidKeyException, IllegalBlockSizeException,
              BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException,
              UnsupportedEncodingException {
          List<DonationDto> donationsToDtos;
  
          User user = authService.getCurrentUser(true);
  
          int ageLegal = Tools.AGE_LEGAL;
  
          int age = Tools.calcUserAge(user);
          boolean isLegalAge = age >= ageLegal;
          int minAge = user.getPreferedMinAge();
          int maxAge = user.getPreferedMaxAge();
  
          if (isLegalAge && minAge < ageLegal) {
              minAge = ageLegal;
          }
          if (!isLegalAge && maxAge >= ageLegal) {
              maxAge = ageLegal - 1;
          }
  
          Date minDate = Tools.ageToDate(maxAge);
          Date maxDate = Tools.ageToDate(minAge);
  
          if (filter == FILTER_RECENT) {
              donationsToDtos = DonationDto.donationsToDtos(userDonationRepo
                              .findTop20ByUserDisabledFalseAndUserDatesDateOfBirthGreaterThanEqualAndUserDatesDateOfBirthLessThanEqualOrderByDateDesc(
                                      minDate, maxDate),
                      user, userService, textEncryptor, maxEntries, ignoreIntention);
          } else if (filter == FILTER_AMOUNT) {
              donationsToDtos = DonationDto.usersToDtos(userRepo.usersDonate(minDate, maxDate), user, userService, textEncryptor,
                      maxEntries, ignoreIntention);
          } else {
              throw new AlovoaException("filter_not_found");
          }
  
          return donationsToDtos;
      }
  
      public void donationReceivedKofi(DonationKofi donation, String key) throws UnknownHostException, MalformedURLException {
  
          try {
              logger.info(objectMapper.writeValueAsString(donation));
          } catch (Exception e) {
              logger.error(e.getMessage());
          }
  
          donation.setEmail(Tools.cleanEmail(donation.getEmail()));
  
          if (kofiKey.equals(key)) {
  
              Date now = new Date();
  
              if (profile.equals(Tools.PROD) && (KOFI_TEST_TRANSACTION_ID.equals(donation.getKofi_transaction_id())
                      || donation.getEmail() != null && KOFI_TEST_EMAIL.equalsIgnoreCase(donation.getEmail()))) {
                  logger.warn("Donation is not valid");
                  return;
              }
  
              User u = null;
  
              if (donation.getFrom_name() != null) {
                  u = userRepo.findByEmail(Tools.cleanEmail(donation.getFrom_name()));
              }
  
              if (u == null && donation.getMessage() != null) {
                  u = userRepo.findByEmail(Tools.cleanEmail(donation.getMessage()));
              }
  
              // in case user forgot, check their Ko-fi email address just in case
              if (u == null && donation.getEmail() != null) {
                  u = userRepo.findByEmail(Tools.cleanEmail(donation.getEmail()));
              }
  
              if (u != null) {
                  double amount = Double.parseDouble(donation.getAmount());
                  UserDonation userDonation = new UserDonation();
                  userDonation.setAmount(amount);
                  userDonation.setDate(now);
                  userDonation.setUser(u);
                  u.getDonations().add(userDonation);
                  u.setTotalDonations(u.getTotalDonations() + amount);
                  u.getDates().setLatestDonationDate(new Date());
                  userRepo.saveAndFlush(u);
              }
          } else {
              logger.error("Invalid key");
          }
      }
  
      public void donationReceivedBmac(DonationBmac data, String key) throws UnknownHostException, MalformedURLException {
  
          try {
              logger.info(objectMapper.writeValueAsString(data));
          } catch (Exception e) {
              logger.error(e.getMessage());
          }
  
          if (bmacKey.equals(key)) {
  
              Date now = new Date();
              DonationBmac.DonationBmacResponse donation = data.getResponse();
  
              if (profile.equals(Tools.PROD) && BMAC_TEST_EMAIL.equalsIgnoreCase(donation.getSupporter_email())) {
                  logger.warn("Donation is not valid");
                  return;
              }
  
              User u = null;
  
              if (donation.getSupporter_name() != null) {
                  u = userRepo.findByEmail(Tools.cleanEmail(donation.getSupporter_name()));
              }
  
              if (u == null && donation.getSupporter_message() != null) {
                  u = userRepo.findByEmail(Tools.cleanEmail(donation.getSupporter_message()));
              }
  
              if (u == null && donation.getSupporter_email() != null) {
                  u = userRepo.findByEmail(Tools.cleanEmail(donation.getSupporter_email()));
              }
  
              if (u != null) {
                  UserDonation userDonation = new UserDonation();
                  double amount = donation.getTotal_amount();// * BMAC_AMOUNT_FACTOR;
                  // amount = (double) Math.round(amount * 100) / 100;
                  userDonation.setAmount(amount);
                  userDonation.setDate(now);
                  userDonation.setUser(u);
                  u.getDonations().add(userDonation);
                  u.setTotalDonations(u.getTotalDonations() + amount);
                  u.getDates().setLatestDonationDate(new Date());
                  userRepo.saveAndFlush(u);
              }
          } else {
              logger.error("Invalid key");
          }
      }
  
  }
  