Looking at your conditions, it sounds like you always want the closest downstream element, regardless of what's upstream or how near or far away that upstream element is.
By default, the BEDOPS closest-features application will report the full characteristics of both the nearest leftmost ("upstream") and rightmost ("downstream") elements.
You can therefore feed the output from this application to awk (or another interpreted language) to just report the TSS element and whatever nearest gene is downstream from it.
As a for instance, first sort your input files:
$ sort-bed unsorted.TSS.bed > TSS.bed
$ sort-bed unsorted.genes.bed > genes.bed
Then run the two sorted BED files through closest-features, piping the results to awk with the correct field separator to pick the downstream gene:
$ closest-features TSS.bed genes.bed \
| awk FS="|" '{ \
tssElement = $1; \
upstreamGene = $2; \
downstreamGene = $3; \
print tssElement"|"downstreamGene; \
}' - \
> answer.bed
The file answer.bed will be a sorted BED file that contains results in the following format:
[ tss-1 ] | [ nearest-downstream-gene-to-tss-1 ]
[ tss-2 ] | [ nearest-downstream-gene-to-tss-2 ]
...
[ tss-n ] | [ nearest-downstream-gene-to-tss-n ]
If you have a different condition for picking a nearest element, you could set up those rules in the awk block above. (Feel free to modify your question if you had something else in mind.)
To test features on the basis of strand, you could modify the awk block as follows:
$ closest-features TSS.bed genes.bed \
| awk FS="|" '{ \
tssRegion = $1; \
upstreamGene = $2; \
downstreamGene = $3; \
split(tssRegion, tssElements, "\t"); \
split(upstreamGene, upstreamGeneElements, "\t"); \
split(downstreamGene, downstreamGeneElements, "\t"); \
tssStart = tssElements[1]; \
tssStop = tssElements[2]; \
upstreamGeneStart = upstreamGeneElements[1]; \
upstreamGeneStop = upstreamGeneElements[2]; \
upstreamGeneStrand = upstreamGeneElements[4]; \
downstreamGeneStart = downstreamGeneElements[1]; \
downstreamGeneStop = downstreamGeneElements[2]; \
downstreamGeneStrand = downstreamGeneElements[4]; \
trueUpstreamGeneDistance = 0; \
trueDownstreamGeneDistance = 0; \
if (upstreamGeneStrand == "+") { \
trueUpstreamGeneDistance = tssStart - upstreamGeneStart; \
} \
else { \
trueUpstreamGeneDistance = tssStart - upstreamGeneStop; \
} \
if (downstreamGeneStrand == "+") { \
trueDownstreamGeneDistance = downstreamGeneStart - tssStop; \
} \
else { \
trueDownstreamGeneDistance = downstreamGeneStop - tssStop; \
} \
if (trueUpstreamGeneDistance > trueDownstreamGeneDistance) { \
print tssRegion"|"downstreamGene; \
} \
else { \
print tssRegion"|"upstreamGene; \
} \
}' - \
> answer.bed