package dev.awesomedev.mirim.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

import java.util.Map;

/**
 * 이 파일이 하는 일:
 * 텔레그램 봇으로 멘토(대표)에게 알림을 보낸다 — 학생 가입, 과제·코딩 제출 등.
 *
 * 학습 포인트 ① — 외부 API 연동의 첫 원칙: "부가 기능이 본 기능을 죽이면 안 된다".
 *   알림은 있으면 좋은 것(nice to have)이고, 가입·제출은 반드시 돼야 하는 것이다.
 *   텔레그램이 점검 중이라고 학생이 가입을 못 하면 주객전도다. 그래서
 *   (1) 모든 예외를 여기서 삼키고(로그만 남긴다), (2) @Async로 딴 스레드에서 보낸다 —
 *   텔레그램 응답이 늦어도 학생의 요청 처리 시간에는 영향이 없다.
 *
 * 학습 포인트 ② — 시크릿은 코드가 아니라 환경변수에.
 *   봇 토큰이 코드나 git에 들어가면 저장소를 보는 모든 사람이 봇을 탈취할 수 있다.
 *   토큰은 운영 서버의 .env 파일에만 있고(TELEGRAM_BOT_TOKEN), 값이 비어 있으면
 *   이 클래스는 조용히 아무것도 안 한다 — 로컬 개발에서 토큰 없이도 앱이 그대로 돈다.
 */
@Service
public class TelegramNotifier {

    private static final Logger log = LoggerFactory.getLogger(TelegramNotifier.class);

    private final String botToken;
    private final String chatId;
    // RestClient: 스프링의 현대식 HTTP 클라이언트 (RestTemplate의 후속).
    private final RestClient restClient = RestClient.create();

    public TelegramNotifier(@Value("${telegram.bot-token:}") String botToken,
                            @Value("${telegram.chat-id:}") String chatId) {
        this.botToken = botToken;
        this.chatId = chatId;
        if (!isEnabled()) {
            log.info("텔레그램 알림 비활성 상태입니다 (TELEGRAM_BOT_TOKEN/CHAT_ID 미설정).");
        }
    }

    private boolean isEnabled() {
        return !botToken.isBlank() && !chatId.isBlank();
    }

    /**
     * 알림 한 건을 보낸다. 실패해도 예외를 밖으로 던지지 않는다.
     *
     * 학습 포인트: @Async — 이 메서드는 호출한 요청 스레드가 아니라 별도 스레드에서 돈다.
     * 호출한 쪽은 기다리지 않고 바로 다음 줄로 넘어간다(fire-and-forget).
     * 주의: @Async는 "다른 빈에서 호출할 때"만 동작한다. 같은 클래스 안에서
     * this.send()로 부르면 프록시를 안 거쳐서 그냥 동기 실행된다 — 스프링 AOP의 대표 함정.
     */
    @Async
    public void send(String text) {
        if (!isEnabled()) {
            return;
        }
        try {
            restClient.post()
                    .uri("https://api.telegram.org/bot{token}/sendMessage", botToken)
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(Map.of("chat_id", chatId, "text", text))
                    .retrieve()
                    .toBodilessEntity();
        } catch (Exception e) {
            // 학습 포인트: e.getMessage()를 그대로 찍지 않는다 — HTTP 에러 메시지에는
            // 요청 URL이 포함되는데, 우리 URL에는 봇 토큰이 들어 있다.
            // "로그에 시크릿이 새는" 흔한 경로라서, 예외의 종류만 남긴다.
            log.warn("텔레그램 알림 전송 실패(무시하고 계속): {}", e.getClass().getSimpleName());
        }
    }
}
