package com.eactive.eai.rms.data.entity.onl.apim.messagerequest;

import com.eactive.apim.portal.template.entity.MessageCode;
import com.eactive.apim.portal.template.entity.MessageRequest;
import com.eactive.apim.portal.template.entity.QMessageRequest;
import com.eactive.eai.rms.common.util.StringUtils;
import com.eactive.eai.rms.data.jpa.AbstractEMSDataSerivce;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.querydsl.core.BooleanBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;

@Service
@Transactional(transactionManager = "transactionManagerForEMS")
public class MessageRequestService
		extends AbstractEMSDataSerivce<MessageRequest, String, MessageRequestEmsRepository> {

	public Page<MessageRequest> findAll(Pageable pageable, MessageRequestUISearch search) {
		QMessageRequest q = QMessageRequest.messageRequest;
		BooleanBuilder predicate = new BooleanBuilder();

		if (StringUtils.isNotBlank(search.getSearchRequestStatus())) {
			predicate.and(q.requestStatus.eq(search.getSearchRequestStatus()));
		}
		if (StringUtils.isNotBlank(search.getSearchMessageCode())) {
			MessageCode.findServiceId(search.getSearchMessageCode())
					.ifPresent(code -> predicate.and(q.messageCode.eq(code)));
		}
		if (StringUtils.isNotBlank(search.getSearchMessageType())) {
			predicate.and(q.messageType.eq(search.getSearchMessageType()));
		}
		if (StringUtils.isNotBlank(search.getSearchRecipient())) {
			predicate.and(q.username.containsIgnoreCase(search.getSearchRecipient()));
		}
		// requestDate 는 yyyyMMddHHmmss 14자리 문자열로 저장(LocalDateTimeToStringConverter14)되므로
		// 고정폭 비교로 기간 필터가 동작한다.
		if (search.getSearchFromDate() != null) {
			predicate.and(q.requestDate.goe(search.getSearchFromDate().atStartOfDay()));
		}
		if (search.getSearchToDate() != null) {
			predicate.and(q.requestDate.loe(search.getSearchToDate().atTime(23, 59, 59)));
		}

		// 발송요청 역순 고정 (Pageable 에 정렬이 없을 때의 안전장치)
		Sort base = Sort.by(Sort.Direction.DESC, "requestDate");
		Sort sort = pageable.getSort().isSorted() ? pageable.getSort() : base;
		Pageable fixed = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);

		return repository.findAll(predicate, fixed);
	}

	/** 특정 일자에 SMS/KAKAO 로 발송 요청된 건수 (UMS 일련번호 채번용). */
	public long countSmsKakaoRequestsOnDate(LocalDate date) {
		QMessageRequest q = QMessageRequest.messageRequest;
		BooleanBuilder predicate = new BooleanBuilder();
		predicate.and(q.messageType.in("SMS", "KAKAO"));
		predicate.and(q.requestDate.goe(date.atStartOfDay()));
		predicate.and(q.requestDate.loe(date.atTime(23, 59, 59)));
		return repository.count(predicate);
	}

	/** PENDING 상태인 건만 FAILED 로 전환한다. */
	public void updateStatusToFailedIfPending(String id) {
		MessageRequest entity = getById(id);
		if (!"PENDING".equals(entity.getRequestStatus())) {
			throw new BizException("PENDING 상태인 건만 변경할 수 있습니다.");
		}
		entity.setRequestStatus("FAILED");
		save(entity);
	}
}
