package com.mosquito.project.service;

import com.mosquito.project.persistence.entity.ApiKeyEntity;
import com.mosquito.project.persistence.repository.ApiKeyRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Optional;

/**
 * API密钥安全管理服务
 * 提供密钥的加密存储、恢复和轮换功能
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiKeySecurityService {

    private final ApiKeyRepository apiKeyRepository;
    
    @Value("${app.security.encryption-key:}")
    private String encryptionKey;
    
    private static final String ALGORITHM = "AES/GCM/NoPadding";
    private static final int TAG_LENGTH_BIT = 128;
    private static final int IV_LENGTH_BYTE = 12;

    /**
     * 生成新的API密钥并加密存储
     */
    @Transactional
    public ApiKeyEntity generateAndStoreApiKey(Long activityId, String description) {
        String rawApiKey = generateRawApiKey();
        String encryptedKey = encrypt(rawApiKey);
        
        ApiKeyEntity apiKey = new ApiKeyEntity();
        apiKey.setActivityId(activityId);
        apiKey.setDescription(description);
        apiKey.setEncryptedKey(encryptedKey);
        apiKey.setIsActive(true);
        apiKey.setCreatedAt(java.time.LocalDateTime.now());
        
        return apiKeyRepository.save(apiKey);
    }

    /**
     * 解密API密钥（仅用于重新显示）
     */
    public String decryptApiKey(ApiKeyEntity apiKey) {
        try {
            return decrypt(apiKey.getEncryptedKey());
        } catch (Exception e) {
            log.error("Failed to decrypt API key for id: {}", apiKey.getId(), e);
            throw new RuntimeException("API密钥解密失败");
        }
    }

    /**
     * 重新显示API密钥（需要额外验证）
     */
    @Transactional(readOnly = true)
    public Optional<String> revealApiKey(Long apiKeyId, String verificationCode) {
        ApiKeyEntity apiKey = apiKeyRepository.findById(apiKeyId)
            .orElseThrow(() -> new RuntimeException("API密钥不存在"));
        
        // 验证密钥状态
        if (!apiKey.getIsActive()) {
            throw new RuntimeException("API密钥已被撤销");
        }
        
        // 验证访问权限（这里可以添加邮箱/手机验证逻辑）
        if (!verifyAccessPermission(apiKey, verificationCode)) {
            log.warn("Unauthorized attempt to reveal API key: {}", apiKeyId);
            throw new RuntimeException("访问权限验证失败");
        }
        
        return Optional.of(decryptApiKey(apiKey));
    }

    /**
     * 轮换API密钥
     */
    @Transactional
    public ApiKeyEntity rotateApiKey(Long apiKeyId) {
        ApiKeyEntity oldKey = apiKeyRepository.findById(apiKeyId)
            .orElseThrow(() -> new RuntimeException("API密钥不存在"));
        
        // 撤销旧密钥
        oldKey.setIsActive(false);
        oldKey.setRevokedAt(java.time.LocalDateTime.now());
        apiKeyRepository.save(oldKey);
        
        // 生成新密钥
        return generateAndStoreApiKey(oldKey.getActivityId(), 
            oldKey.getDescription() + " (轮换)");
    }

    /**
     * 生成原始API密钥
     */
    private String generateRawApiKey() {
        return java.util.UUID.randomUUID().toString() + "-" + 
               java.util.UUID.randomUUID().toString();
    }

    /**
     * 加密密钥
     */
    private String encrypt(String data) {
        try {
            byte[] keyBytes = encryptionKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
            
            byte[] iv = new byte[IV_LENGTH_BYTE];
            new SecureRandom().nextBytes(iv);
            
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, iv);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);
            
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            
            // IV + encrypted data
            byte[] combined = new byte[iv.length + encrypted.length];
            System.arraycopy(iv, 0, combined, 0, iv.length);
            System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);
            
            return Base64.getEncoder().encodeToString(combined);
        } catch (Exception e) {
            log.error("Encryption failed", e);
            throw new RuntimeException("加密失败");
        }
    }

    /**
     * 解密密钥
     */
    private String decrypt(String encryptedData) {
        try {
            byte[] combined = Base64.getDecoder().decode(encryptedData);
            
            // 提取IV和加密数据
            byte[] iv = new byte[IV_LENGTH_BYTE];
            byte[] encrypted = new byte[combined.length - IV_LENGTH_BYTE];
            
            System.arraycopy(combined, 0, iv, 0, IV_LENGTH_BYTE);
            System.arraycopy(combined, IV_LENGTH_BYTE, encrypted, 0, encrypted.length);
            
            byte[] keyBytes = encryptionKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
            
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, iv);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
            
            byte[] decrypted = cipher.doFinal(encrypted);
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("Decryption failed", e);
            throw new RuntimeException("解密失败");
        }
    }

    /**
     * 验证访问权限（可扩展为邮箱/手机验证）
     */
    private boolean verifyAccessPermission(ApiKeyEntity apiKey, String verificationCode) {
        // 这里可以实现复杂的验证逻辑
        // 例如：验证邮箱验证码、手机验证码、安全问题等
        return true; // 简化实现
    }
}