package com.zioinfo.mes.partner;

import com.zioinfo.mes.admin.AuditService;
import com.zioinfo.mes.common.CryptoUtil;
import com.zioinfo.mes.partner.mapper.PartnerMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 거래처 서비스 — 담당자 연락처 PII 를 AES 암호화 저장, 응답은 마스킹.
 *
 * <p>보안 불변 규칙: contactPhone/contactEmail 평문은 절대 저장/응답하지 않는다.
 */
@Service
@RequiredArgsConstructor
public class PartnerService {

    private final PartnerMapper mapper;
    private final CryptoUtil crypto;
    private final AuditService audit;

    public List<MesPartner> list(String partnerType, String status, String keyword) {
        List<MesPartner> list = mapper.findAll(partnerType, status, keyword);
        list.forEach(this::maskForResponse);
        return list;
    }

    public MesPartner get(Long id) {
        MesPartner p = require(id);
        maskForResponse(p);
        return p;
    }

    public MesPartner create(MesPartner p, String actor) {
        if (p.getPartnerCode() == null || p.getPartnerCode().isBlank())
            throw new IllegalArgumentException("ERR-PARTNER-400: partnerCode 필수");
        if (mapper.countByCode(p.getPartnerCode(), null) > 0)
            throw new RuntimeException("ERR-PARTNER-409: 중복 거래처코드");
        encryptPii(p);
        if (p.getStatus() == null) p.setStatus("ACTIVE");
        p.setCreatedBy(actor);
        mapper.insert(p);
        audit.log("PARTNER_CREATE", p.getPartnerCode(), "type=" + p.getPartnerType());
        return get(p.getId());
    }

    public MesPartner update(Long id, MesPartner p, String actor) {
        require(id);
        encryptPii(p);
        p.setId(id);
        mapper.update(p);
        audit.log("PARTNER_UPDATE", p.getPartnerCode(), "id=" + id);
        return get(id);
    }

    public void delete(Long id) {
        MesPartner cur = require(id);
        mapper.delete(id);
        audit.log("PARTNER_DELETE", cur.getPartnerCode(), "id=" + id);
    }

    /** 입력 평문 → *_enc 암호화. 평문 필드는 제거. */
    private void encryptPii(MesPartner p) {
        if (p.getContactPhone() != null && !p.getContactPhone().isBlank()) {
            p.setContactPhoneEnc(crypto.encrypt(p.getContactPhone()));
        }
        if (p.getContactEmail() != null && !p.getContactEmail().isBlank()) {
            p.setContactEmailEnc(crypto.encrypt(p.getContactEmail()));
        }
        p.setContactPhone(null);
        p.setContactEmail(null);
    }

    /** 응답용 — 복호화 후 마스킹. *_enc 는 노출하지 않음. */
    private void maskForResponse(MesPartner p) {
        if (p.getContactPhoneEnc() != null && !p.getContactPhoneEnc().isBlank()) {
            p.setContactPhone(CryptoUtil.mask(crypto.decrypt(p.getContactPhoneEnc())));
        }
        if (p.getContactEmailEnc() != null && !p.getContactEmailEnc().isBlank()) {
            p.setContactEmail(CryptoUtil.mask(crypto.decrypt(p.getContactEmailEnc())));
        }
        p.setContactPhoneEnc(null);
        p.setContactEmailEnc(null);
    }

    private MesPartner require(Long id) {
        MesPartner p = mapper.findById(id);
        if (p == null) throw new RuntimeException("ERR-PARTNER-404: 거래처 없음");
        return p;
    }
}
