package com.zioinfo.kintex.system.infraconfig;

import com.zioinfo.kintex.common.error.ApiException;
import com.zioinfo.kintex.common.error.ErrorCode;
import com.zioinfo.kintex.system.setting.SettingMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 메일/알림 설정 서비스 — sys_setting 의 mail. / notify. 프리픽스 항목을 조회/부분변경한다.
 * 시크릿(secret_yn='Y')은 응답 마스킹, 저장 시 마스킹 값은 미변경 처리(§0-3, 시크릿 미노출·미덮어쓰기).
 */
@Service
public class InfraConfigService {

    private static final String MASK = "********";
    private final SettingMapper mapper;

    public InfraConfigService(SettingMapper mapper) {
        this.mapper = mapper;
    }

    public List<InfraConfigDto> listByPrefix(String prefix) {
        return mapper.findAll().stream()
                .filter(r -> str(r.get("settingKey")) != null && str(r.get("settingKey")).startsWith(prefix))
                .map(InfraConfigService::toMaskedDto)
                .toList();
    }

    @Transactional
    public void update(String prefix, InfraConfigUpdateRequest req, String actorId) {
        if (req.items() == null) {
            return;
        }
        for (InfraConfigUpdateRequest.Item it : req.items()) {
            String key = it.settingKey();
            if (key == null || !key.startsWith(prefix)) {
                throw new ApiException(ErrorCode.VALIDATION, "허용되지 않은 설정 키입니다.");
            }
            Map<String, Object> existing = mapper.findByKey(key);
            if (existing == null) {
                throw new ApiException(ErrorCode.NOT_FOUND, "설정 항목이 없습니다: " + key);
            }
            String secretYn = str(existing.get("secretYn"));
            String value = it.settingValue();
            // 마스킹 그대로 온 시크릿은 미변경(원문 보존).
            if ("Y".equals(secretYn) && MASK.equals(value)) {
                continue;
            }
            Map<String, Object> p = new HashMap<>();
            p.put("settingKey", key);
            p.put("settingValue", value);
            p.put("valueType", str(existing.get("valueType")));
            p.put("description", str(existing.get("description")));
            p.put("secretYn", secretYn);
            p.put("updatedBy", actorId);
            mapper.upsert(p);
        }
    }

    private static InfraConfigDto toMaskedDto(Map<String, Object> r) {
        String secretYn = str(r.get("secretYn"));
        String value = str(r.get("settingValue"));
        if ("Y".equals(secretYn) && value != null && !value.isEmpty()) {
            value = MASK;
        }
        return new InfraConfigDto(str(r.get("settingKey")), value, str(r.get("valueType")),
                str(r.get("description")), secretYn);
    }
    private static String str(Object o) { return o == null ? null : String.valueOf(o); }
}
