package com.devjob.application.client;

import com.devjob.application.dto.JobInfo;
import com.devjob.common.dto.ApiResponse;
import com.devjob.common.exception.BusinessException;
import com.devjob.common.exception.ErrorCode;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientResponseException;

@Component
@RequiredArgsConstructor
public class JobClient {

    private final JobHttpClient jobHttpClient;

    // 바깥층 방어: 공고 서비스 실패율이 임계치를 넘으면 회로 OPEN → 즉시 fallback.
    // 안쪽 재시도·벌크헤드는 JobHttpClient에 있고, 회로는 그 결과(재시도까지 끝난 호출)의 성패를 집계한다.
    @CircuitBreaker(name = "devjob-job", fallbackMethod = "getJobFallback")
    public JobInfo getJob(Long jobId) {
        try {
            ApiResponse<JobInfo> response = jobHttpClient.getJob(jobId);
            if (response == null || response.data() == null) {
                throw new BusinessException(ErrorCode.JOB_NOT_FOUND);
            }
            return response.data();
        } catch (RestClientResponseException e) {
            if (e.getStatusCode().value() == 404) {
                throw new BusinessException(ErrorCode.JOB_NOT_FOUND);
            }
            throw e;
        }
    }

    // 회로 OPEN 또는 호출 실패 시 fallback. ⚠️ ignore-exceptions는 '회로 집계 제외'만 할 뿐
    // fallback 호출까지 막지는 않는다 — 없는 공고 같은 업무 예외도 일단 여기로 들어온다.
    // 그러니 업무 예외는 그대로 되던져(404 유지) 정상 흐름을 지키고, 진짜 서비스 장애(연결 실패·
    // 타임아웃 등)만 서비스 불가(503)로 변환한다.
    public JobInfo getJobFallback(Long jobId, Throwable t) {
        if (t instanceof BusinessException be) {
            throw be;
        }
        throw new BusinessException(ErrorCode.JOB_SERVICE_UNAVAILABLE);
    }
}
