package com.zioinfo.kintex.security;

import com.zioinfo.kintex.auth.EventAccessGuard;
import com.zioinfo.kintex.auth.KintexPrincipal;
import com.zioinfo.kintex.auth.dto.LoginResponse;
import com.zioinfo.kintex.common.ApiResponse;
import com.zioinfo.kintex.security.dto.OtpConfirmRequest;
import com.zioinfo.kintex.security.dto.OtpEnrollRequest;
import com.zioinfo.kintex.security.dto.OtpSetupResponse;
import com.zioinfo.kintex.security.dto.OtpStatusResponse;
import com.zioinfo.kintex.security.dto.OtpVerifyRequest;
import com.zioinfo.kintex.security.dto.SecureLoginRequest;
import com.zioinfo.kintex.security.dto.SecureLoginResponse;
import jakarta.validation.Valid;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

/**
 * 2차 인증(OTP)·잠금 적용 로그인 API (§5B). 기존 /api/auth/login 은 유지하고 본 레이어를 추가 제공한다.
 * <ul>
 *   <li>POST /api/auth/login/secure — 1단계(잠금+자격검증). OTP 사용자면 challengeToken 반환.</li>
 *   <li>POST /api/auth/otp/verify   — 2단계(OTP 코드) → 최종 토큰.</li>
 *   <li>setup/confirm/status/reset  — 로그인 사용자의 OTP 등록/해제(본인).</li>
 * </ul>
 */
@RestController
@RequestMapping("/api/auth")
public class TwoFactorController {

    private final TwoFactorService service;
    private final EventAccessGuard guard;

    public TwoFactorController(TwoFactorService service, EventAccessGuard guard) {
        this.service = service;
        this.guard = guard;
    }

    /** 공개 — 1단계 로그인(잠금+자격검증+OTP 분기). */
    @PostMapping("/login/secure")
    public ApiResponse<SecureLoginResponse> secureLogin(@Valid @RequestBody SecureLoginRequest req) {
        return ApiResponse.ok(service.secureLogin(req.email(), req.password()));
    }

    /** 공개 — 2단계 OTP 검증(등록 사용자) → 최종 토큰. */
    @PostMapping("/otp/verify")
    public ApiResponse<LoginResponse> verifyOtp(@Valid @RequestBody OtpVerifyRequest req) {
        return ApiResponse.ok(service.verifyOtp(req.challengeToken(), req.code()));
    }

    /** 공개(프리오스) — 필수 역할 등록 강제: setup(시크릿·QR 발급). challengeToken 필요. */
    @PostMapping("/otp/enroll/setup")
    public ApiResponse<OtpSetupResponse> enrollSetup(@Valid @RequestBody OtpEnrollRequest req) {
        return ApiResponse.ok(service.enrollSetup(req.challengeToken()));
    }

    /** 공개(프리오스) — 필수 역할 등록 강제: verify(코드 확인·활성화) → 최종 토큰. */
    @PostMapping("/otp/enroll/verify")
    public ApiResponse<LoginResponse> enrollVerify(@Valid @RequestBody OtpVerifyRequest req) {
        return ApiResponse.ok(service.enrollVerify(req.challengeToken(), req.code()));
    }

    /** 인증 — OTP 등록 시작(시크릿·QR 발급). */
    @PostMapping("/otp/setup")
    public ApiResponse<OtpSetupResponse> setup(@AuthenticationPrincipal KintexPrincipal principal) {
        guard.require(principal);
        String label = principal.displayName() != null ? principal.displayName() : principal.userId();
        return ApiResponse.ok(service.setupOtp(principal.userId(), label));
    }

    /** 인증 — OTP 등록 확인(활성화). */
    @PostMapping("/otp/confirm")
    public ApiResponse<Void> confirm(@AuthenticationPrincipal KintexPrincipal principal,
                                     @Valid @RequestBody OtpConfirmRequest req) {
        guard.require(principal);
        service.confirmOtp(principal.userId(), req.code());
        return ApiResponse.ok(null);
    }

    /** 인증 — 본인 OTP 상태. */
    @GetMapping("/otp/status")
    public ApiResponse<OtpStatusResponse> status(@AuthenticationPrincipal KintexPrincipal principal) {
        guard.require(principal);
        return ApiResponse.ok(service.otpStatus(principal.userId()));
    }

    /** 인증 — 본인 OTP 해제. */
    @PostMapping("/otp/reset")
    public ApiResponse<Void> resetSelf(@AuthenticationPrincipal KintexPrincipal principal) {
        guard.require(principal);
        service.resetOtp(principal.userId());
        return ApiResponse.ok(null);
    }
}
