package com.zioinfo.mes.ncr;

import com.zioinfo.mes.admin.AuditService;
import com.zioinfo.mes.ncr.mapper.NcrMapper;
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;

/**
 * 부적합(NCR) 서비스 — 부적합 보고 등록·처리방안(disposition)·CAPA 연계.
 *
 * <p>검사 불합격 시 inspection 모듈이 {@link #createFromSource}로 자동 생성한다.
 */
@Service
@RequiredArgsConstructor
public class NcrService {

    private final NcrMapper mapper;
    private final AuditService audit;

    public List<MesNcr> list(String status, String severity, String itemCode) {
        return mapper.findAll(status, severity, itemCode);
    }

    public MesNcr get(Long id) {
        MesNcr n = mapper.findById(id);
        if (n == null) throw new RuntimeException("ERR-NCR-404: NCR 없음");
        return n;
    }

    public List<Map<String, Object>> statusBoard() {
        return mapper.countByStatus();
    }

    @Transactional
    public MesNcr create(MesNcr n, String actor) {
        if (n.getItemCode() == null || n.getItemCode().isBlank())
            throw new IllegalArgumentException("ERR-NCR-400: itemCode 필수");
        if (n.getNcrNo() == null || n.getNcrNo().isBlank())
            n.setNcrNo(genNo());
        if (n.getSeverity() == null) n.setSeverity("MINOR");
        n.setStatus("OPEN");
        n.setCreatedBy(actor);
        mapper.insert(n);
        audit.log("NCR_CREATE", n.getNcrNo(), "item=" + n.getItemCode() + " defect=" + n.getDefectCode());
        return mapper.findById(n.getId());
    }

    /** 검사 불합격 → NCR 자동 생성(inspection 모듈 호출용). */
    @Transactional
    public MesNcr createFromSource(String itemCode, String lotNo, String refType, String refNo,
                                   String defectCode, double defectQty, String severity, String actor) {
        MesNcr n = new MesNcr();
        n.setItemCode(itemCode);
        n.setLotNo(lotNo);
        n.setRefType(refType);
        n.setRefNo(refNo);
        n.setDefectCode(defectCode);
        n.setDefectQty(defectQty);
        n.setSeverity(severity == null ? "MAJOR" : severity);
        n.setDescription("검사 불합격 자동 부적합 (" + refType + " " + refNo + ")");
        return create(n, actor);
    }

    /** 처리방안 확정 → DISPOSITIONED. */
    @Transactional
    public MesNcr disposition(Long id, String disposition, String actor) {
        MesNcr n = get(id);
        mapper.updateDisposition(id, disposition, "DISPOSITIONED");
        audit.log("NCR_DISPOSITION", n.getNcrNo(), disposition);
        return mapper.findById(id);
    }

    @Transactional
    public MesNcr transition(Long id, String status, String actor) {
        MesNcr n = get(id);
        mapper.updateStatus(id, status);
        audit.log("NCR_STATUS", n.getNcrNo(), n.getStatus() + " -> " + status);
        return mapper.findById(id);
    }

    @Transactional
    public void linkCapa(Long id, Long capaId, String actor) {
        MesNcr n = get(id);
        mapper.linkCapa(id, capaId);
        audit.log("NCR_LINK_CAPA", n.getNcrNo(), "capaId=" + capaId);
    }

    private String genNo() {
        return "NCR-" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
            + "-" + (System.currentTimeMillis() % 100000);
    }
}
