package de.oaa.xxx.hashtag;

import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class HashtagService {

    private static final Pattern HASHTAG_PATTERN =
            Pattern.compile("#([\\wäöüÄÖÜß]{1,100})");

    private final HashtagRepository hashtagRepository;
    private final PostHashtagRepository postHashtagRepository;

    public HashtagService(HashtagRepository hashtagRepository,
                          PostHashtagRepository postHashtagRepository) {
        this.hashtagRepository = hashtagRepository;
        this.postHashtagRepository = postHashtagRepository;
    }

    /** Extract all unique hashtag names (lowercase, no #) from text. */
    public List<String> extractTags(String text) {
        if (text == null || text.isBlank()) return List.of();
        Matcher m = HASHTAG_PATTERN.matcher(text);
        return m.results()
                .map(r -> r.group(1).toLowerCase())
                .distinct()
                .toList();
    }

    /** Save hashtag relationships for a post. Idempotent per tag. */
    @Transactional
    public void saveForPost(String text, String postType, UUID postId, LocalDateTime createdAt) {
        for (String name : extractTags(text)) {
            HashtagEntity ht = hashtagRepository.findByName(name).orElseGet(() -> {
                HashtagEntity h = new HashtagEntity();
                h.setHashtagId(UUID.randomUUID());
                h.setName(name);
                return hashtagRepository.save(h);
            });
            PostHashtagEntity ph = new PostHashtagEntity();
            ph.setId(UUID.randomUUID());
            ph.setHashtagId(ht.getHashtagId());
            ph.setPostType(postType);
            ph.setPostId(postId);
            ph.setCreatedAt(createdAt);
            postHashtagRepository.save(ph);
        }
    }

    /** Remove all hashtag relationships for a deleted post. */
    @Transactional
    public void deleteForPost(String postType, UUID postId) {
        postHashtagRepository.deleteByPostTypeAndPostId(postType, postId);
    }

    /** Autocomplete: names starting with prefix, ordered alphabetically. */
    public List<String> suggest(String prefix, int limit) {
        String normalized = normalize(prefix);
        if (normalized.isEmpty()) return getPopular(limit);
        return hashtagRepository
                .findByNameStartingWithOrderByNameAsc(normalized, PageRequest.of(0, limit))
                .stream()
                .map(HashtagEntity::getName)
                .toList();
    }

    /** Most-used tags over the last 30 days. */
    public List<String> getPopular(int limit) {
        LocalDateTime since = LocalDateTime.now().minusDays(30);
        return postHashtagRepository
                .findPopularSince(since, PageRequest.of(0, limit))
                .stream()
                .map(row -> hashtagRepository.findById(row.getHashtagId())
                        .map(HashtagEntity::getName).orElse(null))
                .filter(Objects::nonNull)
                .toList();
    }

    /** All post references for a given hashtag name (normalised). */
    public List<PostHashtagEntity> getPostRefs(String name) {
        String normalized = normalize(name);
        return hashtagRepository.findByName(normalized)
                .map(ht -> postHashtagRepository.findByHashtagId(ht.getHashtagId()))
                .orElse(List.of());
    }

    private static String normalize(String raw) {
        if (raw == null) return "";
        return raw.replaceAll("[^\\wäöüÄÖÜß]", "").toLowerCase();
    }
}
