package kr.itn.itnhub.org;

import kr.itn.itnhub.contact.Contact;
import kr.itn.itnhub.contact.ContactMapper;
import kr.itn.itnhub.contact.InvalidContactException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class OrganizationService {

    private final OrganizationMapper mapper;
    private final ContactMapper contactMapper;

    public OrganizationService(OrganizationMapper mapper, ContactMapper contactMapper) {
        this.mapper = mapper;
        this.contactMapper = contactMapper;
    }

    public List<OrgResponse> findAll() {
        return mapper.findAll().stream().map(OrgResponse::of).toList();
    }

    /**
     * 담당자관리에서 이미 등록된 담당자를 신청기관/문정원/변호사 역할에 배정한다.
     * null인 필드는 그 역할의 배정을 해제한다는 뜻이며, 매 호출은 세 배정값과
     * 배정일을 통째로 덮어쓴다(부분 갱신이 아니다).
     */
    @Transactional
    public OrgResponse updateAssignments(Long id, AssignmentRequest request) {
        Organization org = mapper.findById(id);
        if (org == null) {
            throw new OrgNotFoundException("기관을 찾을 수 없습니다: " + id);
        }

        validateAssignment(request.applicantContactId(), "APPLICANT", "신청기관 담당자");
        validateAssignment(request.mjContactId(), "MJ", "문정원 담당자");
        validateAssignment(request.lawyerContactId(), "LAWYER", "담당 변호사");

        mapper.updateAssignments(id, request.applicantContactId(), request.mjContactId(),
                request.lawyerContactId(), request.lawyerAssignedDate());

        return OrgResponse.of(mapper.findById(id));
    }

    private void validateAssignment(Long contactId, String expectedCategory, String roleLabel) {
        if (contactId == null) {
            return;
        }
        Contact contact = contactMapper.findById(contactId);
        if (contact == null) {
            throw new InvalidContactException(roleLabel + "로 지정한 담당자를 찾을 수 없습니다: " + contactId);
        }
        if (!expectedCategory.equals(contact.getCategory())) {
            throw new InvalidContactException(roleLabel + "에는 해당 구분의 담당자만 지정할 수 있습니다.");
        }
    }
}
