package com.zioinfo.kintex.auth.integrity;

import com.zioinfo.kintex.auth.integrity.dto.AppIntegrityRequest;
import com.zioinfo.kintex.auth.integrity.dto.AppIntegrityResponse;
import com.zioinfo.kintex.common.error.ApiException;
import com.zioinfo.kintex.common.error.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Locale;
import java.util.Set;

/**
 * B2 — 앱 무결성(위변조 방지) 서버 검증 <b>골격</b>.
 *
 * <p>실제 Play Integrity(Google)/App Attest(Apple) 토큰 검증은 각 플랫폼 서버로의 <b>외부 호출</b>이
 * 필요하다. 온프레미스 외부 API 금지 제약(보안 불변) 하에서는 여기서 실검증을 수행하지 않는다 —
 * 요청 형식만 검증하고 {@code mode=STUB, attested=false} 로 안전하게 반환한다.
 * 모바일은 이 결과로 로그인/기능을 <b>차단하지 않는다</b>(감사 문서 B2: 인계 골격).
 *
 * <p>운영에서 검증기를 붙일 때 진입점(TODO): (1) Android — Google Play Integrity API로 토큰 복호·검증
 * (앱 패키지/서명 지문/nonce 대조), (2) iOS — App Attest 공개키·nonce·receipt 검증. 검증 결과만
 * boolean 으로 반환하고 토큰 원문은 저장/로그 금지(계약 §0-3).
 */
@Service
public class AppIntegrityService {

    private static final Logger log = LoggerFactory.getLogger(AppIntegrityService.class);
    private static final Set<String> PLATFORMS = Set.of("ANDROID", "IOS");
    private static final int MAX_TOKEN_LEN = 8192; // 무결성 토큰 길이 상한(방어적)

    public AppIntegrityResponse verify(String userId, AppIntegrityRequest req) {
        String platform = req.platform() == null ? "" : req.platform().trim().toUpperCase(Locale.ROOT);
        if (!PLATFORMS.contains(platform)) {
            throw new ApiException(ErrorCode.VALIDATION, "platform 은 ANDROID 또는 IOS 여야 합니다.");
        }
        if (req.token() == null || req.token().isBlank() || req.token().length() > MAX_TOKEN_LEN) {
            throw new ApiException(ErrorCode.VALIDATION, "무결성 토큰이 올바르지 않습니다.");
        }
        // 토큰 원문은 로깅하지 않는다 — 수신 사실만 기록(사용자 식별자도 마스킹된 감사에 위임).
        log.info("[integrity] attestation received platform={} (stub verifier, no external call)", platform);
        return new AppIntegrityResponse(false, "STUB",
                "무결성 검증기 미구성(온프레미스) — 서버 검증 골격만 동작합니다. 접근은 차단하지 않습니다.");
    }
}
