package com.eactive.eai.rms.onl.apim.portalterms;

import com.eactive.apim.portal.agreements.entity.AgreementType;
import com.eactive.apim.portal.agreements.entity.Agreements;
import com.eactive.apim.portal.agreements.entity.AgreementsId;
import com.eactive.apim.portal.agreements.service.AgreementsService;
import com.eactive.apim.portal.file.entity.FileDetail;
import com.eactive.apim.portal.file.entity.FileInfo;
import com.eactive.apim.portal.file.service.FileService;
import com.eactive.apim.portal.user.entity.UserInfo;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.data.entity.man.user.UserInfoService;
import com.eactive.eai.rms.data.entity.onl.apim.portalterms.PortalTermsService;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

@Service
@Transactional(transactionManager = "transactionManagerForEMS")
public class PortalTermsManService extends BaseService {
	private final PortalTermsService portalTermsService;
	private final PortalTermsUIMapper portalTermsUIMapper;
	private final AgreementsService agreementsService;
	private final UserInfoService userInfoService;
	private final EditorImageService editorImageService;
	private final FileService fileService;

	@Autowired
	public PortalTermsManService(PortalTermsService portalTermsService,
								 PortalTermsUIMapper portalTermsUIMapper,
								 AgreementsService agreementsService,
								 UserInfoService userInfoService,
								 EditorImageService editorImageService,
								 FileService fileService){
		this.portalTermsService = portalTermsService;
		this.portalTermsUIMapper = portalTermsUIMapper;
		this.agreementsService = agreementsService;
		this.userInfoService = userInfoService;
		this.editorImageService = editorImageService;
		this.fileService = fileService;
	}

	/** 관리 화면에서 '(사용안함)'으로 표시할(=신규 등록에 더 이상 쓰지 않는) 약관 유형 */
	private static final Set<AgreementType> DEPRECATED_AGREEMENT_TYPES = EnumSet.of(
			AgreementType.PRIVACY_POLICY,
			AgreementType.PRIVACY_COLLECT_IND,
			AgreementType.PRIVACY_COLLECT_ORG);

	/**
	 * 관리 화면(콤보/목록)에 표시할 약관 유형 라벨.
	 * 개인정보처리방침 및 개인용/법인용 개인정보수집동의서는 신규 통합 유형 {@link AgreementType#PRIVACY_COLLECT} 등으로
	 * 대체될 예정이므로 '(사용안함)'을 덧붙여 안내한다.
	 * enum 자체의 description은 포털 사용자 화면(AgreementsController#agreementTitle)에서도 쓰이므로 변경하지 않는다.
	 */
	public static String displayLabel(AgreementType type) {
		String label = type.getDescription();
		if (DEPRECATED_AGREEMENT_TYPES.contains(type)) {
			label += "(사용안함)";
		}
		return label;
	}

	private String findName(String userId) {
		if (StringUtils.isBlank(userId)) {
			return "";
		}
		// 등록자/수정자 ID로 사용자를 찾지 못해도(삭제된 사용자, 레거시 시드 데이터 등)
		// 화면 전체가 깨지지 않도록 방어적으로 조회한다. (PortalFaq/PortalInquiry 컨벤션과 동일)
		return userInfoService.findById(userId)
				.map(UserInfo::getUsername)
				.orElse("Unknown");
	}

	public Page<PortalTermsUI> selectList(Pageable pageable, String searchAgreementsType) {
		return portalTermsService.findAll(pageable, searchAgreementsType)
				.map(agreements -> {
					PortalTermsUI portalTermsUI = portalTermsUIMapper.toVo(agreements);
					portalTermsUI.setCreatedByName(findName(agreements.getCreatedBy()));
					portalTermsUI.setLastModifiedByName(findName(agreements.getLastModifiedBy()));
					portalTermsUI.setName(displayLabel(agreements.getAgreementsType()));
					return portalTermsUI;
				});
	}

	public PortalTermsUI selectDetail(String agreementsType, int revision) {
		AgreementsId agreementsId = new AgreementsId(AgreementType.fromCode(agreementsType), revision);
		Agreements agreements = portalTermsService.getById(agreementsId);
		PortalTermsUI portalTermsUI = portalTermsUIMapper.toVo(agreements);
		portalTermsUI.setCreatedByName(findName(agreements.getCreatedBy()));
		portalTermsUI.setLastModifiedByName(findName(agreements.getLastModifiedBy()));
		portalTermsUI.setName(agreements.getAgreementsType().getDescription());

		// 첨부파일 정보 조회
		if (StringUtils.isNotBlank(agreements.getAttachedFileId())) {
			try {
				FileInfo fileInfo = fileService.findById(agreements.getAttachedFileId());
				if (fileInfo != null && !fileInfo.getFileDetails().isEmpty()) {
					FileDetail fileDetail = fileInfo.getFileDetails().get(0);
					portalTermsUI.setAttachedFileName(fileDetail.getOriginalFileName() + "." + fileDetail.getFileExtension());
					portalTermsUI.setAttachedFileSize((long) fileDetail.getFileSize());
				}
			} catch (Exception e) {
				// 파일 조회 실패 시 무시
				logger.warn("첨부파일 조회 실패: {}", agreements.getAttachedFileId(), e);
			}
		}

		return portalTermsUI;
	}

	public void insert(PortalTermsUI portalTermsUI, MultipartFile attachedFile) throws IOException {
		portalTermsUI.setName(AgreementType.fromCode(portalTermsUI.getAgreementsType()).getDescription());
		portalTermsUI.setContents(StringEscapeUtils.unescapeHtml(portalTermsUI.getContents()));
		Agreements agreements = portalTermsUIMapper.toEntity(portalTermsUI);

		// 첨부파일 저장
		if (attachedFile != null && !attachedFile.isEmpty()) {
			FileInfo fileInfo = fileService.createOrUpdateSingleFile(null, attachedFile, attachedFile.getOriginalFilename());
			agreements.setAttachedFileId(fileInfo.getFileId());
		}

		agreementsService.save(agreements);
	}

	public void update(PortalTermsUI portalTermsUI, Set<String> usedFileIds,
					   MultipartFile attachedFile, boolean deleteAttachment) throws IOException {
		Agreements agreements = agreementsService.findById(portalTermsUI.getAgreementsType(), portalTermsUI.getRevision());

		// 원래 내용에서 사용 중이던 파일 ID 추출
		Set<String> originalFileIds = editorImageService.extractFileIds(agreements.getContents());

		// 내용 업데이트
		agreements.setName(AgreementType.fromCode(portalTermsUI.getAgreementsType()).getDescription());
		agreements.setContents(StringEscapeUtils.unescapeHtml(portalTermsUI.getContents()));
		agreements.setPublishedOn(portalTermsUI.getPublishedOn());

		// 첨부파일 처리
		String oldAttachedFileId = agreements.getAttachedFileId();

		if (deleteAttachment && StringUtils.isNotBlank(oldAttachedFileId)) {
			// 첨부파일 삭제 요청
			fileService.deleteFile(oldAttachedFileId);
			agreements.setAttachedFileId(null);
		} else if (attachedFile != null && !attachedFile.isEmpty()) {
			// 새 첨부파일 업로드
			FileInfo fileInfo = fileService.createOrUpdateSingleFile(
					oldAttachedFileId, attachedFile, attachedFile.getOriginalFilename());
			agreements.setAttachedFileId(fileInfo.getFileId());
		}

		agreementsService.save(agreements);

		// 미사용 이미지 정리 (저장 후 비동기적으로 처리)
		editorImageService.cleanupUnusedImages(usedFileIds, originalFileIds);
	}

	public void delete(String agreementsType, Integer revision) {
		// 삭제 전 사용 중인 파일 ID 추출
		Agreements agreements = agreementsService.findById(agreementsType, revision);
		Set<String> fileIdsToDelete = editorImageService.extractFileIds(agreements.getContents());
		String attachedFileId = agreements.getAttachedFileId();

		// 약관 삭제
		agreementsService.delete(agreementsType, revision);

		// 관련 이미지 모두 삭제
		editorImageService.cleanupUnusedImages(new HashSet<>(), fileIdsToDelete);

		// 첨부파일 삭제
		if (StringUtils.isNotBlank(attachedFileId)) {
			try {
				fileService.deleteFile(attachedFileId);
			} catch (Exception e) {
				logger.warn("첨부파일 삭제 실패: {}", attachedFileId, e);
			}
		}
	}
}
