namespace Modules.WMS.Picking.Shared;

public enum PickingScanDecisionKind
{
    RejectLocation,
    AcceptLocation,
    RejectItem,
    AcceptItem
}

public sealed record PickingScanState(
    bool LocationConfirmed,
    string LocationCode,
    string LocationBarcode,
    string ItemBarcode,
    decimal RequiredQty,
    decimal PickedQty);

public sealed record PickingScanDecision(
    PickingScanDecisionKind Kind,
    bool Accepted,
    string Feedback,
    string Message,
    decimal? NewPickedQty = null,
    bool LineCompleted = false)
{
    public string AuditAction => Kind switch
    {
        PickingScanDecisionKind.RejectLocation => "LocationRejected",
        PickingScanDecisionKind.AcceptLocation => "LocationAccepted",
        PickingScanDecisionKind.RejectItem => "ItemRejected",
        PickingScanDecisionKind.AcceptItem => "ItemAccepted",
        _ => "BarcodeScanned"
    };
}

public static class PickingScanStateMachine
{
    public static PickingScanDecision Decide(PickingScanState state, string scannedBarcode)
    {
        var barcode = scannedBarcode.Trim();

        if (!state.LocationConfirmed)
        {
            if (!string.Equals(barcode, state.LocationBarcode, StringComparison.OrdinalIgnoreCase))
                return new(
                    PickingScanDecisionKind.RejectLocation,
                    false,
                    "error",
                    $"잘못된 위치입니다. {state.LocationCode} 위치로 이동하세요.");

            return new(
                PickingScanDecisionKind.AcceptLocation,
                true,
                "success",
                "위치를 확인했습니다. 상품을 스캔하세요.");
        }

        if (!string.Equals(barcode, state.ItemBarcode, StringComparison.OrdinalIgnoreCase))
            return new(
                PickingScanDecisionKind.RejectItem,
                false,
                "error",
                "다른 상품입니다. 화면의 품목과 바코드를 확인하세요.");

        var nextQty = Math.Min(state.PickedQty + 1m, state.RequiredQty);
        var completed = nextQty >= state.RequiredQty;
        return new(
            PickingScanDecisionKind.AcceptItem,
            true,
            "success",
            completed ? "현재 품목을 완료했습니다. 다음 작업을 진행하세요." : "1개 피킹했습니다.",
            nextQty,
            completed);
    }
}
