package dev.ksan.etfoglasiserver.service;

import dev.ksan.etfoglasiserver.dto.EntryDTO;
import dev.ksan.etfoglasiserver.model.Entry;
import dev.ksan.etfoglasiserver.model.Subject;
import dev.ksan.etfoglasiserver.repository.EntryRepo;
import dev.ksan.etfoglasiserver.repository.SubjectRepo;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

@Service
public class EntryService {

  @Autowired
  EntryRepo entryRepo;

  @Autowired
  SubjectService subjectService;

  public List<Entry> getEntries() {
    return entryRepo.findAll();
  }

  public Entry getEntryById(String id) {
    return entryRepo.findById(id).orElseThrow(() -> new RuntimeException("Entry not found"));
  }

  public void addEntry(EntryDTO entry) {

    Subject subject =
            subjectService
                    .findById(entry.getSubjectId());
    Entry newEntry = new Entry(entry);
    newEntry.setSubject(subject);
    entryRepo.save(newEntry);

    subjectService.notifyAsync(newEntry);
  }

  public void addEntry(Entry entry) {
    Optional<Entry> existing = entryRepo.findByTitleAndTimePublishedAndSubject(
            entry.getTitle(),
            entry.getTimePublished(),
            entry.getSubject()
    );

    if (existing.isPresent()) {
      System.out.println("Duplicate entry, skipping");
      return;
    }

    try {
      entryRepo.save(entry);
    } catch (Exception e) {
      System.out.println("Duplicate");
      return;
    }
    subjectService.notifyAsync(entry);
  }

  public void updateEntry(EntryDTO entry) {
    Subject subject =
            subjectService
                    .findById(entry.getSubjectId());
    Entry updateEntry = entryRepo.findById(entry.getId().toString()).orElseThrow(() -> new RuntimeException("Entry not found"));
    updateEntry.setSubject(subject);
    if (entry.getTitle() != null) {
      updateEntry.setTitle(entry.getTitle());
    }
    if (entry.getInfo_entry() != null) {
      updateEntry.setInfo_entry(entry.getInfo_entry());
    }
    if (entry.getParagraph() != null) {
      updateEntry.setParagraph(entry.getParagraph());
    }
    if (entry.getFilepath() != null) {
      updateEntry.setFilepath(entry.getFilepath());
    }
    if (entry.getTime_published() != null) {
      updateEntry.setTime_published(entry.getTime_published());
    }
    entryRepo.save(updateEntry);
  }

  public void deleteEntry(String id) {
    entryRepo.deleteById(id);
  }


  public Page<Entry> getEntries(UUID subjectId, String groupName, int page) {
    Pageable pageable = PageRequest.of(page, 20, Sort.by("timePublished").descending());

    if (subjectId != null && groupName != null) {
      Subject subject = subjectService.findById(subjectId);
      return entryRepo.findBySubjectAndGroupNameOrderByTimePublishedDesc(subject, groupName, pageable);
    }
    if (subjectId != null) {
      Subject subject = subjectService.findById(subjectId);
      return entryRepo.findBySubjectOrderByTimePublishedDesc(subject, pageable);
    }
    if (groupName != null) {
      return entryRepo.findByGroupNameOrderByTimePublishedDesc(groupName, pageable);
    }

    return entryRepo.findAllByOrderByTimePublishedDesc(pageable);
  }

  public List<String> getAllGroups() {
    List<Entry> allEntries = entryRepo.findAll();

    // Extract unique group names
    return allEntries.stream()
            .map(Entry::getGroup)
            .filter(Objects::nonNull)
            .distinct()
            .sorted()
            .toList();
  }
}
