package com.zioinfo.esn.auth;

import com.zioinfo.esn.auth.mapper.UserAuthMapper;
import com.zioinfo.esn.uiws.auth.TwoFactorService;
import com.zioinfo.esn.uiws.common.UiwsApiException;
import com.zioinfo.esn.uiws.common.UiwsErrorCode;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * ESN 인증 서비스.
 * - 기존 단일 JWT 로그인 보존(2FA off 또는 미설정 시 회귀 0).
 * - UIWS 2FA 레이어(이메일 코드) 추가: 2FA on 이면 1차 통과 후 verify-token + 이메일코드 발급.
 *   실패 누적 max-login-fail 회 시 계정 잠금.
 */
@Service
@RequiredArgsConstructor
public class AuthService {

    private final UserAuthMapper userMapper;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;
    private final TwoFactorService twoFactorService;

    /**
     * 1차 로그인. 2FA 활성 시 verify-token + 이메일코드 흐름으로 분기,
     * 비활성 시 기존처럼 access 토큰 즉시 발급.
     *
     * @return 2FA off: { token, type, twofa:"false" }
     *         2FA on : { verifyToken, step:"EMAIL", maskedEmail, twofa:"true" }
     */
    public Map<String, String> login(String username, String password) {
        EsnUser user = userMapper.findByUsername(username);

        // 잠금 우선 차단(존재하는 계정에 한해 잠금 메시지 — 존재 여부 누설 최소화)
        if (user != null && twoFactorService.isLocked(user)) {
            throw new UiwsApiException(UiwsErrorCode.ACCOUNT_LOCKED);
        }
        if (user == null || !user.isActive()) {
            throw new RuntimeException("ERR-AUTH-001: 존재하지 않거나 비활성 계정");
        }
        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            // 2FA 활성 시 실패 누적/잠금. 비활성 시 기존 동작(메시지만) 유지.
            if (twoFactorService.isEnabled()) {
                twoFactorService.recordLoginFailure(username);
                EsnUser after = userMapper.findByUsername(username);
                if (after != null && Boolean.TRUE.equals(after.getLocked())) {
                    throw new UiwsApiException(UiwsErrorCode.ACCOUNT_LOCKED);
                }
            }
            throw new RuntimeException("ERR-AUTH-002: 비밀번호 불일치");
        }

        // 비밀번호 검증 통과
        if (twoFactorService.isEnabled()) {
            Map<String, String> step1 = twoFactorService.beginTwoFactor(user);
            return Map.of(
                    "twofa", "true",
                    "verifyToken", step1.get("verifyToken"),
                    "step", step1.get("step"),
                    "maskedEmail", step1.getOrDefault("maskedEmail", ""));
        }

        // 2FA 비활성 — 기존 단일 로그인 흐름(회귀 0)
        userMapper.resetLoginFail(username);
        userMapper.updateLastLogin(username);
        String token = jwtUtil.generate(username, user.getRole(), user.getTenantCode());
        return Map.of("twofa", "false", "token", token, "type", "Bearer");
    }

    public Map<String, String> me(String token) {
        return Map.of(
            "username", jwtUtil.getUsername(token),
            "role", jwtUtil.getRole(token),
            "tenant", jwtUtil.getTenant(token) != null ? jwtUtil.getTenant(token) : ""
        );
    }
}
