All Light All Light All Light!
JavaScript (Node.js), 393 391 378 bytes



a=&gt;(R=[],f=(a,[x,...y],z,Y)=&gt;x?f(a.map(t=&gt;[...t]),y,z,Y)||f(a,y,[...z,x],Y.map(p=&gt;p.map(q=&gt;q-Y[x[0]][x[1]]?q:Y[x[2]][x[3]])),--a[x[0]][x[1]],--a[x[2]][x[3]]):/[1-9]/.test(a)|Y.some(t=&gt;t.some(u=&gt;u-Y[I][J]&amp;&amp;u))?0:z)(a=a.map(A=(b,i)=&gt;b.map((x,j)=&gt;x&amp;&amp;(A[i]+1&amp;&amp;R.push([i,A[i],i,j]),f[j]+1&amp;&amp;R.push([f[j],j,i,j]),A[I=i]=j,f[J=j]=i,x/=x&gt;0))),[...R,...R],C=[],a.map(p=&gt;p.map(q=&gt;q&amp;&amp;++C)))


Try it online!

a=&gt;(
    a=a.map(
        A=(b,i)=&gt;
            b.map(
                (x,j)=&gt;
                    x&amp;&amp;(                                  // A[i]+1 &lt;==&gt; A[i] is NOT NaN
                        A[i]+1&amp;&amp;R.push([i,A[i],i,j]),     // Use A and f to store last
                        f[j]+1&amp;&amp;R.push([f[j],j,i,j]),     // existance of row and column
                        A[I=i]=j,f[J=j]=i,x/=x&gt;0          // -1 =&gt; -Inf, +n =&gt; n
                    )
            ),
            R=[],
            f=([x,...y],z,Y)=&gt;
                x?
                    f(
                        y,[...z,x],
                        Y.map(p=&gt;p.map(q=&gt;q-Y[x[0]][x[1]]?q:Y[x[2]][x[3]])), // merge
                        --a[x[0]][x[1]],--a[x[2]][x[3]]
                    )||
                    f(y,z,Y,++a[x[0]][x[1]],++a[x[2]][x[3]])
                :
                    /[1-9]/.test(a)|
                    Y.some(t=&gt;t.some(u=&gt;u-Y[I][J]&amp;&amp;u)) // not totally merged
                    ?0:z
    ),f)([...R,...R],[],a.map(p=&gt;p.map(q=&gt;q&amp;&amp;++C),C=0)
)