package com.zioinfo.mes.receiving;

import com.zioinfo.mes.admin.AuditService;
import com.zioinfo.mes.inventory.InventoryService;
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;

/**
 * 입고 서비스 — 공급사 자재/제품 입고·검수.
 *
 * <p>흐름: REQUESTED → (INSPECTING) → ACCEPTED(입고확정·재고증가) / REJECTED.
 * ACCEPTED 시 {@link InventoryService#inbound}로 RECEIVE 수불 + 잔고 증가(원장 일원화).
 */
@Service
@RequiredArgsConstructor
public class ReceivingService {

    private final ReceivingMapper mapper;
    private final InventoryService inventory;
    private final AuditService audit;

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

    public MesReceiving get(Long id) {
        MesReceiving r = mapper.findById(id);
        if (r == null) throw new RuntimeException("ERR-RECV-404: 입고 없음");
        return r;
    }

    @Transactional
    public MesReceiving create(MesReceiving r, String actor) {
        if (r.getItemCode() == null || r.getItemCode().isBlank())
            throw new IllegalArgumentException("ERR-RECV-400: itemCode 필수");
        if (r.getQty() == null || r.getQty() <= 0)
            throw new IllegalArgumentException("ERR-RECV-400: qty 는 0보다 커야 합니다");
        if (r.getReceivingNo() == null || r.getReceivingNo().isBlank())
            r.setReceivingNo("RCV-" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
                + "-" + (System.currentTimeMillis() % 100000));
        boolean inspect = Boolean.TRUE.equals(r.getInspectionRequired());
        r.setStatus(inspect ? "INSPECTING" : "REQUESTED");
        r.setCreatedBy(actor);
        mapper.insert(r);
        audit.log("RECEIVING_CREATE", r.getReceivingNo(), "item=" + r.getItemCode() + " qty=" + r.getQty());
        return mapper.findById(r.getId());
    }

    /**
     * 입고 확정(ACCEPT) — 검사 결과 반영 후 재고 증가.
     * 검사 필요 입고는 inspectionResult=PASS 여야 확정 가능.
     */
    @Transactional
    public MesReceiving accept(Long id, String inspectionResult, String actor) {
        MesReceiving r = get(id);
        if ("ACCEPTED".equals(r.getStatus()))
            throw new RuntimeException("ERR-RECV-409: 이미 입고확정됨");
        if (Boolean.TRUE.equals(r.getInspectionRequired()) && !"PASS".equalsIgnoreCase(
                inspectionResult == null ? r.getInspectionResult() : inspectionResult)) {
            throw new RuntimeException("ERR-RECV-409: 검사 합격(PASS) 후에만 입고확정 가능");
        }
        mapper.updateStatus(id, "ACCEPTED", inspectionResult);
        inventory.inbound("RECEIVE", r.getItemCode(), r.getWarehouseCode(), r.getLocationCode(),
            r.getLotNo(), r.getQty(), "RECEIVING", r.getReceivingNo(), actor);
        audit.log("RECEIVING_ACCEPT", r.getReceivingNo(), "qty=" + r.getQty() + " → 재고증가");
        return mapper.findById(id);
    }

    @Transactional
    public MesReceiving reject(Long id, String reason, String actor) {
        MesReceiving r = get(id);
        mapper.updateStatus(id, "REJECTED", "FAIL");
        audit.log("RECEIVING_REJECT", r.getReceivingNo(), reason == null ? "" : reason);
        return mapper.findById(id);
    }
}
