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

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.portalorg.entity.PortalOrg;
import com.eactive.apim.portal.portaluser.entity.PortalUser;
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums;
import com.eactive.apim.portal.portaluser.entity.PortalUserPrivacyAgreement;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.common.spring.LocaleMessage;
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgService;
import com.eactive.eai.rms.data.entity.onl.apim.portaluser.PortalUserService;
import com.eactive.eai.rms.data.entity.onl.apim.portaluser.PortalUserUISearch;
import com.eactive.eai.rms.data.entity.onl.apim.portaluserterms.PortalUserTermsService;
import com.eactive.eai.rms.onl.apim.masking.MaskingUtils;
import com.eactive.eai.rms.onl.apim.portalorg.PortalOrgManService;
import com.eactive.eai.rms.onl.common.exception.BizException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Service
@Transactional(transactionManager = "transactionManagerForEMS")
@RequiredArgsConstructor
@Slf4j
public class PortalUserManService extends BaseService {

	private final PortalUserService portalUserService;
	private final PortalUserUIMapper portalUserUIMapper;
	private final LocaleMessage localeMessage;
	private final PortalOrgService portalOrgService;
	private final FileService fileService;
	private final PortalOrgManService portalOrgManService;
//	private final PasswordEncoder passwordEncoder;
	private final PasswordEncoder kjbSafedbPasswordEncoder;
	private final PortalUserTermsService portalUserTermsService;


	public Page<PortalUserUI> selectList(Pageable pageable, PortalUserUISearch portalUserUISearch) {
		Page<PortalUser> portalUser = portalUserService.findAll(pageable, portalUserUISearch);
		return portalUser.map(entity -> {
			PortalUserUI ui = convertToUIWithMaskOption(entity, false);

			if (entity.getPortalOrg() != null) {
				setPortalOrgUI(entity, ui);
			}
			return ui;
		});
	}

	public PortalUserUI selectDetail(String id, boolean isMasked) {
		PortalUser portalUser = portalUserService.getById(id);
		PortalUserUI portalUserUI = convertToUIWithMaskOption(portalUser, isMasked);

		if (portalUser.getPortalOrg() != null) {
			setPortalOrgUI(portalUser, portalUserUI);
		}
		return portalUserUI;
	}

	public PortalUserUI selectDetailUnmask(String id) {
		return selectDetail(id, false);
	}

	private void setPortalOrgUI(PortalUser portalUser, PortalUserUI portalUserUI) {
		portalOrgManService.getPortalOrgUI(portalUser.getPortalOrg().getId())
				.ifPresent(orgUI -> {
					// IP 마스킹 처리 추가
					if (StringUtils.isNotBlank(orgUI.getIpWhitelist())) {
						orgUI.setIpWhitelist(MaskingUtils.maskIpAddress(orgUI.getIpWhitelist()));
					}

					portalUserUI.setPortalOrgUIs(orgUI);
					if (StringUtils.isNotBlank(portalUser.getPortalOrg().getCompRegFile())) {
						FileInfo fileInfo = fileService.findById(portalUser.getPortalOrg().getCompRegFile());
						orgUI.setFileInfo(fileInfo);
						FileDetail fileDetail = fileInfo.getFileDetails().get(0);
						orgUI.setFileName(fileDetail.getOriginalFileName() + "." + fileDetail.getFileExtension());
					}
				});
	}
	/**
	 * PortalUser 엔티티를 UI 객체로 변환하고, 필요한 경우 마스킹 처리를 수행합니다.
	 *
	 * @param portalUser 변환할 PortalUser 엔티티
	 * @param isMasked true 인 경우 개인정보(이름, 이메일, 로그인 ID, 휴대폰번호)를 마스킹 처리
	 * @return 변환된 PortalUserUI 객체 (마스킹 처리 여부에 따라 처리됨)
	 */
	private PortalUserUI convertToUIWithMaskOption(PortalUser portalUser, boolean isMasked) {
		PortalUserUI ui = portalUserUIMapper.toVo(portalUser);

		if (ui != null && isMasked) {
			if (StringUtils.isNotBlank(ui.getUserName())) {
				ui.setUserName(MaskingUtils.maskName(ui.getUserName()));
			}
			if (StringUtils.isNotBlank(ui.getEmailAddr())) {
				ui.setEmailAddr(MaskingUtils.maskEmailId(ui.getEmailAddr()));
			}
			if (StringUtils.isNotBlank(ui.getLoginId())) {
				ui.setLoginId(MaskingUtils.maskEmailId(ui.getLoginId()));
			}
			if (StringUtils.isNotBlank(ui.getMobileNumber())) {
				ui.setMobileNumber(MaskingUtils.maskPhoneNumber(ui.getMobileNumber()));
			}
		}

		return ui;
	}

	public void insert(PortalUserUI portalUserUI) throws Exception {
		// 중복체크
		if (portalUserService.existsByLoginId(portalUserUI.getLoginId())) {
			throw new BizException(localeMessage.getString("portalUser.checkUserMsg1"));
		}

		PortalUser portalUser = portalUserUIMapper.toEntity(portalUserUI);
		portalUser.setPasswordHash(kjbSafedbPasswordEncoder.encode("!" + portalUserUI.getLoginId()));
		portalUser.setLoginFailureCount(0);
		portalUser.setAccountLockYn("N");
		portalUser.setEmailAddr(portalUserUI.getLoginId());
		portalUser.setId(null);

		if (StringUtils.isNotBlank(portalUserUI.getOrgId())) {
			portalUser.setPortalOrg(portalOrgService.getById(portalUserUI.getOrgId()));
		}
		portalUserService.save(portalUser);
	}

	public void update(PortalUserUI portalUserUI) {
		PortalUser portalUser = portalUserService.getById(portalUserUI.getId());
		portalUserUIMapper.updateToEntity(portalUserUI, portalUser);

		if (StringUtils.isNotBlank(portalUserUI.getOrgId())) {
			PortalOrg portalOrg = portalOrgService.getById(portalUserUI.getOrgId());
			portalUser.setPortalOrg(portalOrg);
		}

		portalUserService.save(portalUser);
	}

	public void removeUser(String id) {
		PortalUser portalUser = portalUserService.getById(id);

		// 이용약관 동의 이력 삭제
		List<PortalUserPrivacyAgreement> agreements = portalUserTermsService.findAllByCreatedBy(portalUser.getId());
		if (!agreements.isEmpty()) {
			portalUserTermsService.deleteAll(agreements);
		}

		String withdrawalDate = "-d" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));

		portalUser.setLoginId(portalUser.getId()  + withdrawalDate);
		portalUser.setEmailAddr(portalUser.getId() + withdrawalDate);
		portalUser.setUserName("삭제된사용자");
		portalUser.setMobileNumber("");

		portalUser.setUserStatus(PortalUserEnums.UserStatus.REMOVED);

		portalUserService.save(portalUser);
	}

	public boolean checkDuplicateId(String loginId) {
		return !portalUserService.existsByLoginId(loginId);
	}

	public void passwordReset(String id) {
		PortalUser portalUser = portalUserService.getById(id);

		// 패스워드를 초기 패스워드("!" + loginId)로 초기화
		portalUser.setPasswordHash(kjbSafedbPasswordEncoder.encode("!" + portalUser.getLoginId()));

		// 로그인 실패 횟수 초기화
		portalUser.setLoginFailureCount(0);

		// 계정 잠금 해제
		portalUser.setAccountLockYn("N");

		portalUserService.save(portalUser);

		log.info("Password reset for user: {}", portalUser.getLoginId());
	}

}
