package com.eactive.eai.rms.ext.djb.webhook.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

@Slf4j
@Service
@RequiredArgsConstructor
public class WebhookReceiveService {

    private final ObjectMapper objectMapper;

    
    private String secretKey = "HW8JtFpkPmQqsVmr0Rb81P4qDypaNIVbGf3ZNMMPfyerhOHshoKABLaMBo1HA4BldTxhw1NjYmVnoPu9IIV7cyRXjecL3b2UctyR7DnVaJausltZLLr8Qm4Bzs4wRmgf";

    private static final String HMAC_ALGORITHM  = "HmacSHA256";
    private static final long   TIMESTAMP_LIMIT = 5 * 60 * 1000L; // 5분 (ms)

    /* ------------------------------------------------------------------ */
    /*  서명 검증                                                            */
    /* ------------------------------------------------------------------ */

    /**
     * 수신된 서명과 payload 로 재계산한 서명을 비교
     * 헤더값 형식 : "sha256={hex값}"
     */
    public boolean verifySignature(String rawPayload, String receivedSignature) {
        try {
            // "sha256=" 접두어 제거
            String receivedHex = receivedSignature.startsWith("sha256=")
                    ? receivedSignature.substring(7)
                    : receivedSignature;

            String expectedHex = generateSignature(rawPayload);

            // 타이밍 공격 방지 : MessageDigest.isEqual 사용
            return MessageDigest.isEqual(
                    expectedHex.getBytes(StandardCharsets.UTF_8),
                    receivedHex.getBytes(StandardCharsets.UTF_8)
            );
        } catch (Exception e) {
            log.error("[Webhook] 서명 검증 중 오류 발생", e);
            return false;
        }
    }

    /* ------------------------------------------------------------------ */
    /*  타임스탬프 검증                                                       */
    /* ------------------------------------------------------------------ */

    /**
     * 요청 타임스탬프가 현재 시각 기준 5분 이내인지 확인 (Replay Attack 방지)
     */
    public boolean verifyTimestamp(String timestampStr) {
        try {
            long requestTime = Long.parseLong(timestampStr);
            long now         = System.currentTimeMillis();
            return Math.abs(now - requestTime) <= TIMESTAMP_LIMIT;
        } catch (NumberFormatException e) {
            log.warn("[Webhook] 타임스탬프 파싱 실패: {}", timestampStr);
            return false;
        }
    }

    /* ------------------------------------------------------------------ */
    /*  이벤트 처리                                                          */
    /* ------------------------------------------------------------------ */

    /**
     * eventType 에 따라 분기 처리
     */
    public void process(String eventType, String rawPayload) throws Exception {
        JsonNode root = objectMapper.readTree(rawPayload);
        JsonNode data = root.path("data");

        log.info("[Webhook] 이벤트 처리 시작 - eventType: {}", eventType);

        switch (eventType) {
            case "CONTROL_START":
            	handleControlStart(data);
                break;
            case "CONTROL_END":
            	handleControlEnd(data);
                break;
            case "ERROR_START":
            	handleErrorStart(data);
                break;
            default:
                log.warn("[Webhook] 처리되지 않은 이벤트 - eventType: {}", eventType);
                break;
        }

        log.info("[Webhook] 이벤트 처리 완료 - eventType: {}", eventType);
    }

    /* ------------------------------------------------------------------ */
    /*  이벤트별 핸들러 (비즈니스 로직 구현)                                    */
    /* ------------------------------------------------------------------ */

    private void handleControlStart(JsonNode data) {
        log.info("[Webhook] CONTROL_START 처리 - data: {}", data);
        // TODO: 점검시작 처리 로직
    }
    private void handleControlEnd(JsonNode data) {
        log.info("[Webhook] CONTROL_END 처리 - data: {}", data);
        // TODO: 점검종료 처리 로직
    }
    private void handleErrorStart(JsonNode data) {
        log.info("[Webhook] ERROR_START 처리 - data: {}", data);
        // TODO: 장애시작 처리 로직
    }


    /* ------------------------------------------------------------------ */
    /*  공통 유틸                                                            */
    /* ------------------------------------------------------------------ */

    private String generateSignature(String payload) throws Exception {
        Mac mac = Mac.getInstance(HMAC_ALGORITHM);
        SecretKeySpec keySpec = new SecretKeySpec(
                secretKey.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM);
        mac.init(keySpec);
        byte[] hash = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(hash);
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}