package com.zioinfo.kintex.system.errorlog;

import com.zioinfo.kintex.common.PageResponse;
import com.zioinfo.kintex.tenant.TenantContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

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

/**
 * 오류 로그 서비스 — 기록(best-effort)·조회. 저장은 요약 1줄만(스택트레이스·민감정보 금지, §0-3).
 * 기록 실패가 원 예외 응답을 막지 않도록 예외를 삼킨다.
 */
@Service
public class ErrorLogService {

    private static final Logger log = LoggerFactory.getLogger(ErrorLogService.class);
    private final ErrorLogMapper mapper;

    public ErrorLogService(ErrorLogMapper mapper) {
        this.mapper = mapper;
    }

    /** 예외 요약 기록. summary 는 호출자가 스택 제외한 1줄 요약을 넘긴다. */
    public void record(String errorCode, String summary, String path, String method, String actorId) {
        try {
            Map<String, Object> p = new HashMap<>();
            p.put("tenantId", TenantContext.currentTenantId());
            p.put("errorCode", errorCode);
            p.put("summary", trunc(summary, 500));
            p.put("path", trunc(path, 300));
            p.put("method", method);
            p.put("actorId", actorId);
            mapper.insert(p);
        } catch (Exception e) {
            log.warn("[ERROR_LOG] record skipped: {}", e.getClass().getSimpleName());
        }
    }

    public PageResponse<ErrorLogDto> list(String errorCode, int page, int size) {
        int p = Math.max(page, 0);
        int s = size <= 0 ? 20 : Math.min(size, 200);
        String tenantId = TenantContext.currentTenantId();
        List<Map<String, Object>> rows = mapper.search(tenantId, errorCode, s, p * s);
        long total = mapper.count(tenantId, errorCode);
        return PageResponse.of(rows.stream().map(ErrorLogService::toDto).toList(), p, s, total);
    }

    private static ErrorLogDto toDto(Map<String, Object> r) {
        return new ErrorLogDto(lng(r.get("id")), str(r.get("errorCode")), str(r.get("summary")),
                str(r.get("path")), str(r.get("method")), str(r.get("actorId")), str(r.get("createdAt")));
    }
    private static String trunc(String v, int max) {
        if (v == null) return null;
        return v.length() <= max ? v : v.substring(0, max);
    }
    private static String str(Object o) { return o == null ? null : String.valueOf(o); }
    private static long lng(Object o) {
        if (o instanceof Number n) return n.longValue();
        return o == null ? 0L : Long.parseLong(String.valueOf(o));
    }
}
