package com.storycove.service;

import com.storycove.entity.RefreshToken;
import com.storycove.repository.RefreshTokenRepository;
import com.storycove.util.JwtUtil;
import jakarta.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Optional;

@Service
public class RefreshTokenService {

    private static final Logger logger = LoggerFactory.getLogger(RefreshTokenService.class);

    private final RefreshTokenRepository refreshTokenRepository;
    private final JwtUtil jwtUtil;

    public RefreshTokenService(RefreshTokenRepository refreshTokenRepository, JwtUtil jwtUtil) {
        this.refreshTokenRepository = refreshTokenRepository;
        this.jwtUtil = jwtUtil;
    }

    /**
     * Create a new refresh token
     */
    public RefreshToken createRefreshToken(String libraryId, String userAgent, String ipAddress) {
        String token = jwtUtil.generateRefreshToken();
        LocalDateTime expiresAt = LocalDateTime.now().plusSeconds(jwtUtil.getRefreshExpirationMs() / 1000);

        RefreshToken refreshToken = new RefreshToken(token, expiresAt, libraryId, userAgent, ipAddress);
        return refreshTokenRepository.save(refreshToken);
    }

    /**
     * Find a refresh token by its token string
     */
    public Optional<RefreshToken> findByToken(String token) {
        return refreshTokenRepository.findByToken(token);
    }

    /**
     * Verify and validate a refresh token
     */
    public Optional<RefreshToken> verifyRefreshToken(String token) {
        return refreshTokenRepository.findByToken(token)
                .filter(RefreshToken::isValid);
    }

    /**
     * Revoke a specific refresh token
     */
    @Transactional
    public void revokeToken(RefreshToken token) {
        token.setRevokedAt(LocalDateTime.now());
        refreshTokenRepository.save(token);
    }

    /**
     * Revoke all refresh tokens for a specific library
     */
    @Transactional
    public void revokeAllByLibraryId(String libraryId) {
        refreshTokenRepository.revokeAllByLibraryId(libraryId, LocalDateTime.now());
        logger.info("Revoked all refresh tokens for library: {}", libraryId);
    }

    /**
     * Revoke all refresh tokens (e.g., for logout all)
     */
    @Transactional
    public void revokeAll() {
        refreshTokenRepository.revokeAll(LocalDateTime.now());
        logger.info("Revoked all refresh tokens");
    }

    /**
     * Clean up expired tokens periodically
     * Runs daily at 3 AM
     */
    @Scheduled(cron = "0 0 3 * * ?")
    @Transactional
    public void cleanupExpiredTokens() {
        refreshTokenRepository.deleteExpiredTokens(LocalDateTime.now());
        logger.info("Cleaned up expired refresh tokens");
    }
}
