package com.zioinfo.mes.oee;

import com.zioinfo.mes.admin.AuditService;
import com.zioinfo.mes.oee.mapper.OeeMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * OEE 서비스 — 가동률·성능·품질 산식 + 비가동/불량 집계.
 */
@Service
@RequiredArgsConstructor
public class OeeService {

    private final OeeMapper mapper;
    private final AuditService audit;

    public List<MesOeeRecord> list(String equipmentCode, int limit) {
        return mapper.findAll(equipmentCode, limit <= 0 ? 100 : limit);
    }

    public MesOeeRecord create(MesOeeRecord r, String actor) {
        if (r.getEquipmentCode() == null) throw new IllegalArgumentException("ERR-OEE-400: equipmentCode 필수");
        r.setCreatedBy(actor);
        mapper.insert(r);
        audit.log("OEE_RECORD", r.getEquipmentCode(), "date=" + r.getRecordDate());
        return mapper.findById(r.getId());
    }

    public List<Map<String, Object>> downtimePareto(int days) {
        return mapper.downtimePareto(days <= 0 ? 30 : days);
    }

    /** OEE 계산 — 한 기록의 가동률/성능/품질/OEE. */
    public Map<String, Object> compute(MesOeeRecord r) {
        double planned = nz(r.getPlannedTimeMin());
        double run = nz(r.getRunTimeMin());
        double ideal = nz(r.getIdealCycleMin());
        double total = nz(r.getTotalCount());
        double good = nz(r.getGoodCount());

        double availability = planned > 0 ? clamp(run / planned) : 0;
        double performance = run > 0 ? clamp((ideal * total) / run) : 0;
        double quality = total > 0 ? clamp(good / total) : 0;
        double oee = availability * performance * quality;

        Map<String, Object> m = new LinkedHashMap<>();
        m.put("equipmentCode", r.getEquipmentCode());
        m.put("availability", round4(availability));
        m.put("performance", round4(performance));
        m.put("quality", round4(quality));
        m.put("oee", round4(oee));
        m.put("oeePercent", round2(oee * 100));
        return m;
    }

    /** id 기준 OEE 계산. */
    public Map<String, Object> computeById(Long id) {
        MesOeeRecord r = mapper.findById(id);
        if (r == null) throw new RuntimeException("ERR-OEE-404: OEE 기록 없음");
        return compute(r);
    }

    private double nz(Double d) { return d == null ? 0 : d; }
    private double clamp(double d) { return Math.max(0, Math.min(1, d)); }
    private double round4(double d) { return Math.round(d * 10000.0) / 10000.0; }
    private double round2(double d) { return Math.round(d * 100.0) / 100.0; }
}
