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

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.file.service.FileTypeContext;
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.ApprovalStatus;
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.OrgStatus;
import com.eactive.apim.portal.portaluser.entity.PortalUser;
import com.eactive.eai.common.util.UUID;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgService;
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgUISearch;
import com.eactive.eai.rms.data.entity.onl.apim.portaluser.PortalUserService;
import com.eactive.eai.rms.onl.apim.masking.MaskingUtils;
import com.eactive.eai.rms.onl.apim.portaluser.PortalUserCorpManagerUI;
import com.eactive.eai.rms.onl.apim.portaluser.PortalUserCorpManagerUIMapper;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

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

    private final PortalOrgService portalOrgService;
    private final PortalOrgUIMapper portalOrgUIMapper;
    private final PortalUserService portalUserService;
    private final PortalUserCorpManagerUIMapper portalUserCorpManagerUIMapper;
    private final FileService fileService;

    public Page<PortalOrgUI> selectList(Pageable pageable, PortalOrgUISearch portalOrgUISearch) {
        Page<PortalOrg> portalOrg = portalOrgService.findAll(pageable, portalOrgUISearch);
        return portalOrg.map(entity -> convertToUIWithMaskOption(entity, true));
    }

    public PortalOrgUI selectDetail(String id) {
        PortalOrg portalOrg = portalOrgService.getById(id);
        return portalOrgUIMapper.toVo(portalOrg);
    }

    public void insert(PortalOrgUI portalOrgUI) throws IOException {
        // 사업자등록증 필수 체크에서 제외함.
//        if (portalOrgUI.getCompRegFileUpload() == null) {
//            throw new BizException("사업자 등록증을 업로드 해주세요.");
//        }

        decodePortalOrgUIFields(portalOrgUI);
        PortalOrg portalOrg = portalOrgUIMapper.toEntity(portalOrgUI);

        if (!StringUtils.isEmpty(portalOrg.getCompRegFile())) {
            MultipartFile file = portalOrgUI.getCompRegFileUpload();
            if (file != null) {
                String decodedFileName = decodeString(portalOrgUI.getFileName());
                FileTypeContext.setFileType("certificate");
                FileInfo fileInfo = fileService.createOrUpdateSingleFile(null, file, decodedFileName);
                portalOrg.setCompRegFile(fileInfo.getFileId());
            }
        }

        if (portalOrg.getOrgStatus() == null) {
            portalOrg.setOrgStatus(OrgStatus.READY);
        }

        if (portalOrg.getApprovalStatus() == null) {
            portalOrg.setApprovalStatus(ApprovalStatus.PENDING);
        }

        if (portalOrg.getId() == null || portalOrg.getId().isEmpty()) {
            portalOrg.setId(UUID.randomUUID().toString());
        }
        portalOrgService.save(portalOrg);
    }

    private String decodeString(String value) {
        if (value == null) {
            return null;
        }
//		return new String(value.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); // local
        return new String(value.getBytes(Charset.defaultCharset()), StandardCharsets.UTF_8);    // server
    }

    private void decodePortalOrgUIFields(PortalOrgUI portalOrgUI) {
        portalOrgUI.setOrgName(decodeString(portalOrgUI.getOrgName()));         // 법인명
        portalOrgUI.setOrgCode(decodeString(portalOrgUI.getOrgCode()));         // 법인명
        portalOrgUI.setOrgIndustryType(decodeString(portalOrgUI.getOrgIndustryType())); // 업종
        portalOrgUI.setOrgSectors(decodeString(portalOrgUI.getOrgSectors()));   // 업태
        portalOrgUI.setCeoName(decodeString(portalOrgUI.getCeoName()));         // 대표자성명
        portalOrgUI.setOrgAddr(decodeString(portalOrgUI.getOrgAddr()));         // 사업장소재지
        portalOrgUI.setServiceName(decodeString(portalOrgUI.getServiceName())); // 서비스명
        portalOrgUI.setScPhoneNumber(decodeString(portalOrgUI.getScPhoneNumber()));
        portalOrgUI.setOrgPhoneNumber(decodeString(portalOrgUI.getOrgPhoneNumber()));
    }

    public void update(PortalOrgUI portalOrgUI) throws IOException {
        decodePortalOrgUIFields(portalOrgUI);
        PortalOrg portalOrg = portalOrgService.getById(portalOrgUI.getId());
        portalOrgUIMapper.updateToEntity(portalOrgUI, portalOrg);

        // 새로운 파일이 업로드된 경우에만 파일 처리
        if (portalOrgUI.getCompRegFileUpload() != null && !portalOrgUI.getCompRegFileUpload().isEmpty()) {
            MultipartFile file = portalOrgUI.getCompRegFileUpload();
            String decodedFileName = decodeString(portalOrgUI.getFileName());
            FileTypeContext.setFileType("certificate");
            FileInfo fileInfo = fileService.createOrUpdateSingleFile(portalOrg.getCompRegFile(), file, decodedFileName);
            portalOrgUI.setCompRegFile(fileInfo.getFileId());
            // 엔티티에 새 파일 ID 설정
            portalOrgUIMapper.updateToEntity(portalOrgUI, portalOrg);
        }

        portalOrgService.save(portalOrg);
    }

    public void removeOrg(String id) {
        PortalOrg portalOrg = portalOrgService.getById(id);
        portalOrg.setOrgName("삭제된법인");
        portalOrg.setOrgStatus(OrgStatus.REMOVED);
        portalOrgService.save(portalOrg);
    }

    public Map<String, Object> selectDetailWithUsers(String id) {
        return getDetailWithUsers(id, true);
    }

    private Map<String, Object> getDetailWithUsers(String id, boolean isMasked) {
        PortalOrg portalOrg = portalOrgService.findById(id)
                .orElseThrow(() -> new BizException("해당 법인을 찾을 수 없습니다."));

        PortalOrgUI portalOrgUI = convertToUIWithMaskOption(portalOrg, isMasked);

        Map<String, Object> result = new HashMap<>();
        result.put("portalOrg", portalOrgUI);

        // Corporate Manager 처리
        portalUserService.findCorporateManagerByOrgId(id)
                .map(corporateManager -> convertCorporateManagerToUIWithMaskOption(corporateManager, isMasked))
                .ifPresent(corporateManagerUI -> result.put("corporateManager", corporateManagerUI));

        // 파일 정보 추가
        setFileInfo(portalOrg, portalOrgUI);

        return result;
    }

    private PortalOrgUI convertToUIWithMaskOption(PortalOrg portalOrg, boolean isMasked) {
        PortalOrgUI ui = portalOrgUIMapper.toVo(portalOrg);

        if (ui != null && isMasked) {
            if (StringUtils.isNotBlank(ui.getIpWhitelist())) {
                ui.setIpWhitelist(MaskingUtils.maskIpAddress(ui.getIpWhitelist()));
            }
        }
        return ui;
    }

    private PortalUserCorpManagerUI convertCorporateManagerToUIWithMaskOption(PortalUser corporateManager, boolean isMasked) {
        PortalUserCorpManagerUI ui = portalUserCorpManagerUIMapper.toVo(corporateManager);

        return ui;
    }

    private void setFileInfo(PortalOrg portalOrg, PortalOrgUI ui) {
        Optional.ofNullable(portalOrg.getCompRegFile())
                .filter(StringUtils::isNotBlank)
                .map(fileService::findById)
                .map(fileInfo -> {
                    ui.setFileInfo(fileInfo);
                    if (!fileInfo.getFileDetails().isEmpty()) {
                        FileDetail fileDetail = fileInfo.getFileDetails().get(0);
                        ui.setFileName(fileDetail.getOriginalFileName() + "." + fileDetail.getFileExtension());
                    }
                    return fileInfo;
                });
    }

    public Optional<PortalOrgUI> getPortalOrgUI(String portalOrgId) {
        return portalOrgService.findById(portalOrgId)
                .map(portalOrgUIMapper::toVo);
    }

    public Optional<PortalOrgUI> getPortalOrgUI(String portalOrgId, boolean isMasked) {
        return portalOrgService.findById(portalOrgId)
                .map(portalOrg -> {
                    PortalOrgUI ui = portalOrgUIMapper.toVo(portalOrg);
                    if (ui != null) {
                        // IP 마스킹 처리
                        if (isMasked && StringUtils.isNotBlank(ui.getIpWhitelist())) {
                            ui.setIpWhitelist(MaskingUtils.maskIpAddress(ui.getIpWhitelist()));
                        }

                        // 파일 정보 처리 추가
                        setFileInfo(portalOrg, ui);
                    }
                    return ui;
                });
    }

    public Optional<PortalOrg> findById(String orgId) {
        return portalOrgService.findById(orgId);
    }
}
