package com.mosquito.project.service;

import com.mosquito.project.persistence.entity.ShortLinkEntity;
import com.mosquito.project.persistence.repository.ShortLinkRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.security.SecureRandom;
import java.nio.charset.StandardCharsets;
import java.net.URI;
import java.net.URLDecoder;
import java.util.Optional;

@Service
public class ShortLinkService {

    private static final Logger log = LoggerFactory.getLogger(ShortLinkService.class);

    private final ShortLinkRepository repository;
    private static final char[] ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    private static final int DEFAULT_CODE_LEN = 8;
    private final SecureRandom random = new SecureRandom();

    public ShortLinkService(ShortLinkRepository repository) {
        this.repository = repository;
    }

    public ShortLinkEntity create(String originalUrl) {
        String code = generateUniqueCode(DEFAULT_CODE_LEN);
        ShortLinkEntity e = new ShortLinkEntity();
        e.setCode(code);
        e.setOriginalUrl(originalUrl);
        try {
            URI uri = URI.create(originalUrl);
            String query = uri.getQuery();
            if (query != null) {
                for (String p : query.split("&")) {
                    String[] kv = p.split("=", 2);
                    if (kv.length == 2) {
                        if ("activityId".equals(kv[0])) {
                            e.setActivityId(Long.parseLong(URLDecoder.decode(kv[1], StandardCharsets.UTF_8)));
                        } else if ("inviter".equals(kv[0])) {
                            e.setInviterUserId(Long.parseLong(URLDecoder.decode(kv[1], StandardCharsets.UTF_8)));
                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.debug("Failed to parse query params from URL: {}", ex.getMessage());
        }
        e.setCreatedAt(java.time.OffsetDateTime.now(java.time.ZoneOffset.UTC));
        return repository.save(e);
    }

    public Optional<ShortLinkEntity> findByCode(String code) {
        return repository.findByCode(code);
    }

    private String generateUniqueCode(int len) {
        for (int i = 0; i < 5; i++) {
            String code = randomCode(len);
            if (!repository.existsByCode(code)) {
                return code;
            }
        }
        return randomCode(len + 2);
    }

    private String randomCode(int len) {
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            sb.append(ALPHABET[random.nextInt(ALPHABET.length)]);
        }
        return sb.toString();
    }
}
