package com.devjob.application.service;

import com.devjob.application.client.JobClient;
import com.devjob.application.domain.Application;
import com.devjob.application.dto.ApplicationResponse;
import com.devjob.application.dto.JobInfo;
import com.devjob.common.exception.BusinessException;
import com.devjob.common.exception.ErrorCode;
import com.devjob.application.repository.ApplicationRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * EP08: 시즌1 EP24의 ApplicationService를 옮겨왔다.
 * - Member/Job 엔티티 직접 조회 대신, jobId 유효성은 devjob-job 호출(JobClient)로 확인한다.
 * - 회원 존재 여부는 더 이상 이 서비스에서 검증하지 않는다 — userId는 (지금은 임시로) 호출자가
 *   직접 전달하며, EP20 게이트웨이 도입 후 X-User-Id 헤더로 신뢰성을 확보한다.
 * - EP26~27에서 지원 완료 시 ApplicationAppliedEvent를 발행해 알림 서비스와 연동한다.
 */
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ApplicationService {

    private final ApplicationRepository applicationRepository;
    private final JobClient jobClient;

    @Transactional
    public ApplicationResponse apply(Long userId, Long jobId) {
        JobInfo job = jobClient.getJob(jobId);

        if ("CLOSED".equals(job.status())) {
            throw new BusinessException(ErrorCode.JOB_CLOSED);
        }

        if (applicationRepository.existsByUserIdAndJobId(userId, jobId)) {
            throw new BusinessException(ErrorCode.ALREADY_APPLIED);
        }

        Application application = Application.builder()
                .userId(userId)
                .jobId(jobId)
                .build();

        Application saved = applicationRepository.save(application);
        return ApplicationResponse.of(saved, job);
    }

    public List<ApplicationResponse> findMyApplications(Long userId) {
        return applicationRepository.findByUserIdOrderByCreatedAtDesc(userId).stream()
                .map(application -> ApplicationResponse.of(application, jobClient.getJob(application.getJobId())))
                .toList();
    }

    public ApplicationResponse findById(Long userId, Long applicationId) {
        Application application = applicationRepository.findById(applicationId)
                .orElseThrow(() -> new BusinessException(ErrorCode.APPLICATION_NOT_FOUND));

        if (!application.getUserId().equals(userId)) {
            throw new BusinessException(ErrorCode.APPLICATION_NOT_FOUND);
        }

        return ApplicationResponse.of(application, jobClient.getJob(application.getJobId()));
    }
}
