package dev.ksan.etfoglasiserver.service;

import com.google.firebase.messaging.FirebaseMessagingException;
import dev.ksan.etfoglasiserver.model.Entry;
import dev.ksan.etfoglasiserver.model.NotificationMethod;
import dev.ksan.etfoglasiserver.model.Subject;
import dev.ksan.etfoglasiserver.model.User;
import dev.ksan.etfoglasiserver.repository.SubjectRepo;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class SubjectService {

  @Autowired private SubjectRepo subjectRepo;

  @Autowired
  private NotificationService notificationService;

    @Autowired
    private UserService userService;



  public List<Subject> getSubjects() {
    return subjectRepo.findAll();
  }

  public Subject getSubject(UUID id) {
    return subjectRepo.findById(id).orElseThrow(() -> new RuntimeException("Subject not found"));
  }

  public void addSubject(Subject subject) {

    if (subjectRepo.existsByName(subject.getName())) {
      throw new RuntimeException("Subject already exists");
    }

    Subject newSubject = new Subject();
    newSubject.setName(subject.getName());
    newSubject.setCode(subject.getCode());
    subjectRepo.save(newSubject);
  }

  public void updateSubject(Subject subject) {

    Subject existingSubject =
        subjectRepo
            .findById(subject.getId())
            .orElseThrow(() -> new RuntimeException("Subject not found"));
    existingSubject.setName(subject.getName());
    existingSubject.setCode(subject.getCode());
    subjectRepo.save(existingSubject);
  }

  public void deleteSubject(UUID id) {
    subjectRepo.deleteById(id);
  }

  public Subject getSubject(String name) {
    return subjectRepo.findByName(name);
  }
  public Subject findById(UUID id) {
    return subjectRepo.findById(id).orElseThrow(() -> new RuntimeException("Subject not found"));
  }


  //TODO move this and make an EventListener for this

  @Async
  public void notifyAsync(Entry entry) {

    // The scraper couldn't always match an announcement to a known subject, in
    // which case there's nobody to notify. Guard against the NPE that would
    // otherwise be thrown (and silently swallowed) on this async thread.
    if (entry.getSubject() == null) return;

    List<User> users =
            userService.findUsersBySubjectId(entry.getSubject().getId());

    if (users == null || users.isEmpty()) return;

    for (User user : users) {

      if (user.getNotificationMethod() != NotificationMethod.PUSH_NOTIFICATION)
        continue;

      try{

        notificationService.sendToUser(user, entry.getTitle(), entry.getParagraph());
      }catch (FirebaseMessagingException e) {
        e.printStackTrace();
      }
    }
  }


  public long count() {

    return subjectRepo.count();
  }
}
