package com.gcsc.connection.auth.service;

import com.gcsc.connection.auth.dto.LoginRequest;
import com.gcsc.connection.auth.dto.LoginResponse;
import com.gcsc.connection.auth.dto.TokenRefreshRequest;
import com.gcsc.connection.auth.dto.TokenRefreshResponse;
import com.gcsc.connection.auth.jwt.JwtTokenProvider;
import com.gcsc.connection.common.exception.BusinessException;
import com.gcsc.connection.common.exception.ErrorCode;
import com.gcsc.connection.user.entity.SnpUser;
import com.gcsc.connection.user.repository.SnpUserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class AuthService {

    private final SnpUserRepository userRepository;
    private final JwtTokenProvider jwtTokenProvider;
    private final PasswordEncoder passwordEncoder;

    /**
     * 로그인 처리: 사용자 인증 후 JWT 토큰 발급
     */
    @Transactional
    public LoginResponse login(LoginRequest request) {
        SnpUser user = userRepository.findByLoginId(request.loginId())
            .orElseThrow(() -> new BusinessException(ErrorCode.INVALID_CREDENTIALS));

        if (!Boolean.TRUE.equals(user.getIsActive())) {
            throw new BusinessException(ErrorCode.USER_DISABLED);
        }

        if (!passwordEncoder.matches(request.password(), user.getPasswordHash())) {
            throw new BusinessException(ErrorCode.INVALID_CREDENTIALS);
        }

        String accessToken = jwtTokenProvider.generateAccessToken(
            user.getUserId(), user.getLoginId(), user.getRole().name());
        String refreshToken = jwtTokenProvider.generateRefreshToken(user.getUserId());

        user.updateLastLoginAt();

        log.info("사용자 로그인 성공: {}", user.getLoginId());

        return new LoginResponse(
            accessToken,
            refreshToken,
            user.getLoginId(),
            user.getUserName(),
            user.getRole().name(),
            jwtTokenProvider.getAccessTokenExpiration()
        );
    }

    /**
     * 토큰 갱신: Refresh Token으로 새 Access Token 발급
     */
    @Transactional(readOnly = true)
    public TokenRefreshResponse refresh(TokenRefreshRequest request) {
        if (!jwtTokenProvider.validateToken(request.refreshToken())) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID);
        }

        Long userId = jwtTokenProvider.getUserId(request.refreshToken());
        SnpUser user = userRepository.findById(userId)
            .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND));

        if (!Boolean.TRUE.equals(user.getIsActive())) {
            throw new BusinessException(ErrorCode.USER_DISABLED);
        }

        String accessToken = jwtTokenProvider.generateAccessToken(
            user.getUserId(), user.getLoginId(), user.getRole().name());

        return new TokenRefreshResponse(accessToken, jwtTokenProvider.getAccessTokenExpiration());
    }
}
