package com.zioinfo.mes.inspection;

import com.zioinfo.mes.admin.AuditService;
import com.zioinfo.mes.ai.AiService;
import com.zioinfo.mes.inspection.mapper.InspectionMapper;
import com.zioinfo.mes.ncr.NcrService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * 검사 서비스 — IQC/IPQC/OQC 검사 등록·판정·불합격 시 NCR 자동 생성.
 *
 * <p>판정(judge)은 {@link AiService#inspectionJudge}(Ollama+Java 폴백)로 측정값 vs 스펙 자동 판정.
 * FAIL 시 {@link NcrService#createFromSource}로 부적합을 자동 기록한다.
 */
@Service
@RequiredArgsConstructor
public class InspectionService {

    private final InspectionMapper mapper;
    private final AiService ai;
    private final NcrService ncrService;
    private final AuditService audit;

    public List<MesInspection> list(String inspectionType, String result, String itemCode) {
        return mapper.findAll(inspectionType, result, itemCode);
    }

    public MesInspection get(Long id) {
        MesInspection i = mapper.findById(id);
        if (i == null) throw new RuntimeException("ERR-INS-404: 검사 없음");
        return i;
    }

    public List<Map<String, Object>> passRate(int days) {
        return mapper.passRateByType(days);
    }

    @Transactional
    public MesInspection create(MesInspection i, String actor) {
        if (i.getItemCode() == null || i.getItemCode().isBlank())
            throw new IllegalArgumentException("ERR-INS-400: itemCode 필수");
        if (i.getInspectionType() == null) i.setInspectionType("IQC");
        if (i.getInspectionNo() == null || i.getInspectionNo().isBlank())
            i.setInspectionNo("INS-" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
                + "-" + (System.currentTimeMillis() % 100000));
        if (i.getResult() == null) i.setResult("PENDING");
        if (i.getSampleSize() == null) i.setSampleSize(1);
        i.setCreatedBy(actor);
        mapper.insert(i);
        audit.log("INSPECTION_CREATE", i.getInspectionNo(), "type=" + i.getInspectionType() + " item=" + i.getItemCode());
        return mapper.findById(i.getId());
    }

    /**
     * 검사 판정 — 측정값 vs 스펙. AI 판정 보조 호출.
     * FAIL 시 NCR 자동 생성.
     */
    @Transactional
    public Map<String, Object> judge(Long id, double measured, Double lsl, Double usl, Double target,
                                     double defectQty, String defectCode, String actor) {
        MesInspection i = get(id);
        Map<String, Object> judgement = ai.inspectionJudge(measured, lsl, usl, target);
        String result = String.valueOf(judgement.getOrDefault("judgement", "PASS"));
        String measurements = "[{\"measured\":" + measured + ",\"lsl\":" + lsl + ",\"usl\":" + usl
            + ",\"judge\":\"" + result + "\"}]";
        mapper.updateResult(id, result, measurements, defectQty);
        audit.log("INSPECTION_JUDGE", i.getInspectionNo(), "result=" + result + " measured=" + measured);
        if ("FAIL".equals(result)) {
            String severity = "OQC".equals(i.getInspectionType()) ? "CRITICAL" : "MAJOR";
            ncrService.createFromSource(i.getItemCode(), i.getLotNo(), "INSPECTION", i.getInspectionNo(),
                defectCode == null ? "INSP-FAIL" : defectCode, defectQty, severity, actor);
            judgement.put("ncrCreated", true);
        }
        return judgement;
    }

    /** 수동 판정 결과 입력(PASS/FAIL). FAIL 시 NCR 자동 생성. */
    @Transactional
    public MesInspection setResult(Long id, String result, double defectQty, String defectCode, String actor) {
        MesInspection i = get(id);
        String r = result == null ? "PASS" : result.toUpperCase();
        if (!r.equals("PASS") && !r.equals("FAIL"))
            throw new IllegalArgumentException("ERR-INS-400: 결과는 PASS/FAIL");
        mapper.updateResult(id, r, null, defectQty);
        audit.log("INSPECTION_RESULT", i.getInspectionNo(), "result=" + r);
        if ("FAIL".equals(r)) {
            String severity = "OQC".equals(i.getInspectionType()) ? "CRITICAL" : "MAJOR";
            ncrService.createFromSource(i.getItemCode(), i.getLotNo(), "INSPECTION", i.getInspectionNo(),
                defectCode == null ? "INSP-FAIL" : defectCode, defectQty, severity, actor);
        }
        return mapper.findById(id);
    }
}
