package com.demo1.login;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.lotte.chamomile.core.exception.BusinessException;
import net.lotte.chamomile.core.exception.ChamomileExceptionCode;
import net.lotte.chamomile.module.security.SecurityService;
import net.lotte.chamomile.module.security.jwt.provider.JwtAuthInterface;
import net.lotte.chamomile.module.security.jwt.vo.JwtRequest;
import net.lotte.chamomile.module.web.variable.ChamomileResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PSource;
import javax.servlet.http.HttpServletRequest;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Map;

@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/security")
public class SecurityController implements SecurityControllerDoc {

    private final SecurityService securityService;
    private final JwtAuthInterface jwtAuthInterface;

    @PostMapping("/jwt/authenticate")
    public ChamomileResponse<Map<String, String>> authenticate(@RequestBody JwtRequest jwtRequest) throws Exception {
        return new ChamomileResponse<>();
    }

    @PostMapping("/jwt/refresh-token")
    public ChamomileResponse<Map<String, String>> refreshToken(HttpServletRequest request) throws Exception {
        return new ChamomileResponse<>();
    }

    @GetMapping("/jwt/secret-key")
    public ChamomileResponse<String> secretKey() throws InvalidKeySpecException, NoSuchAlgorithmException {

        SecureRandom secureRandom = new SecureRandom(); // 스레드 안전한 랜덤 생성기
        Base64.Encoder base64Encoder = Base64.getUrlEncoder(); // URL 안전한 인코딩에 사용
        String originalPassword = generateKey(32, secureRandom, base64Encoder);
        byte[] salt = new byte[16]; // You should use a unique and secure salt for each user!

        // Generate derived key
        KeySpec spec = new PBEKeySpec(originalPassword.toCharArray(), salt, 65536, 512);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        byte[] derivedKey = factory.generateSecret(spec).getEncoded();

        if (StringUtils.isNotBlank(Base64.getEncoder().encodeToString(derivedKey))) {
            return new ChamomileResponse<>(Base64.getEncoder().encodeToString(derivedKey));
        }
        return new ChamomileResponse<>(ChamomileExceptionCode.SERVER_ERROR, "");
    }

    public static String generateKey(int length, SecureRandom secureRandom, Base64.Encoder base64Encoder) {
        byte[] randomBytes = new byte[length];
        secureRandom.nextBytes(randomBytes);
        return base64Encoder.encodeToString(randomBytes);
    }
    @GetMapping("/jwt/rsa-password")
    public ChamomileResponse<String> encrypt(String plainText) throws Exception {
        String encryptedText = null;
        String publicKeyConfig = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7n9T9y2rflLzbudMjm+PslBSQTGGCPaySE5ayghbr6lRZ4QDA+WTf2SDxjBWh91J7C2NkTQ6FSHHxdFemvHBIKZtACNOBgsQaO7Q0Sh5nrl34XSVrq53hMIHC7OmP98Wqjqdz6c6BQFicyefGZffOtyG4eBjWtu0oAd0/wW902X0sVnzn/g30V6r1IvvE3ov8Nq49W2F7g1goh1IMPtay2lSvc1259vviV1ONOsqyzmrDY+q9kkEW6bXckZH53Soihhgf+bUA36qagV7EbQKorNwNHYyICHZRRxiFem7Y/vlYWIOamJNSdlPHRdl4epAPMHDVvRxGpteNWkVbr3ybQIDAQAB";

        try {
            // 평문으로 전달받은 공개키를 사용하기 위해 공개키 객체 생성
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] bytePublicKey = Base64.getDecoder().decode(publicKeyConfig.getBytes());
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(bytePublicKey);
            PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

            // 만들어진 공개키 객체로 암호화 설정
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            OAEPParameterSpec oaepParameterSpecJCE = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParameterSpecJCE);

            // 평문을 암호문으로 변환하는 과정
            byte[] plainBytes = plainText.getBytes();
            byte[] encryptedBytes = cipher.doFinal(plainBytes);
            encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new BusinessException("server error");
        }
        return new ChamomileResponse<>(encryptedText);
    }
}

