Justme's answer is very possible. Expanded here.
I have used photodiodes directly connected to a GPIO pin, along with a small-value capacitor to detect light. A LED should work as detector too.
The GPIO digital pins must be able to switch from input to output - most are versatile-enough to do this. It may help if the GPIO pins can generate an interrupt-on-change, but polling can be done too. If possible, GPIO2 should have a Schmitt-style input characteristic, although I have used a straight CMOS input-style successfully too. A microcontroller timer is useful too, to measure the time to charge the capacitor.

simulate this circuit – Schematic created using CircuitLab
Using a red laser as a light source should make detection easy, since it is so intense: much more intense than ambient light (unless your LED is looking directly at the sun).
When you want the LED to emit light:
- RA5 becomes an output, logic low.
- RA4 becomes an output, logic high. R1 limits LED current.
When you want the LED to detect laser light:
- RA5 is an output, logic high.
- RA4 is an output, logic low, so that C1 discharges down to Vss (GND)...LED will be un-lit....
- RA4 then switches to input, and a timer is started simultaneously.
- At this point photocurrents detected in LED charge C1 toward Vdd.
- RA4 is monitored until it switches to logic high. Then timer is stopped.
The timer gives an indication of detected light. Its count value is small when the LED sees a bright light. Its count value is high when the LED sees a dim light.
A smaller capacitor at C1 can detect quite low light levels (candle flame). A 27 pf capacitor for C1 works fine. At 330 pf, the LED could still detect a candle flame 30 cm away (a 5mm dia. LED with lens). For bright environments, a capacitor 1 nf or more might be appropriate. A GREEN LED worked too. The 24-bit counter in the software below can make a measurement up to 4 seconds before overflow.
I have measured leakage currents on GPIO input pins to be far below spec-sheet values in many Microchip's PIC microcontrollers - below 1nA.
Edit: This project interested me enough to code it up, build and try out on a breadboard. At room temperature, dark current of LED and leakage current of microcontroller input pin RA4 were impressively low. LED photocurrents of a fraction of a nanoamp could be detected reliably.
As a light detector, the RED LED could charge up the 330pf capacitor to the +2v threshold in a few seconds in a rather dim indoor room. A white sheet of paper reflecting window-light to the LED increased count rate enough to light up the LED.
;RED LED light detector. When excited with light, the reverse-biased LED is used
;as a current source to charge a capacitor.
;Ambient light on RED LED charges the capacitor slowly. A counter uses
;internal clock to measure charge time, which is proportional to current.
;
; RA4 (pin 3) on LED anode. Add a current-limiting series resistor!
; RA5 (pin 2) is used as digital output to drive LED cathode
; MCLR (pin 4) is used as MCLR (master reset)
; RA0, RA1, RA2 go high at end of charge period for 32us, then tristate
;TTL logic levels are used on I/O pins rather than schmitt thresholds high=2V
;April 2021 glen_geek
;------------------------------------------------------
PROCESSOR 12F1572 ;from MICROCHIP
#include <xc.inc>
#define skpnc btfsc STATUS,0 ;why doesn't pic-as accommodate these macros?
#define skpc btfss STATUS,0 ;why doesn't pic-as accommodate these macros?
#define clrc bcf STATUS,0 ;why doesn't pic-as accommodate these macros?
#define skpnz btfsc STATUS,2 ;why doesn't pic-as accommodate these macros?
#define skpz btfss STATUS,2 ;why doesn't pic-as accommodate these macros?
config FOSC=INTOSC, WDTE=OFF, PWRTE=OFF, MCLRE=ON, CP=OFF, BOREN=OFF, CLKOUTEN=OFF
config WRT=OFF, PLLEN=OFF, STVREN=ON, BORV=LO, LPBOREN=OFF, LVP=OFF
;------------------------------------------------------
PSECT udata_shr,class=COMMON ;precious RAM addressable from every RAM page
; ORG 0x70
ambient: DS 3 ;measured ambient light level detected by LED
current: DS 3 ;current light level detected by LED
cnt: DS 3 ;a general-purpose counter (or local variable).
GLOBAL ambient
;------------------------------------------------------
PSECT resetVec, class=CODE, delta=2 ;linker should map this to address 0000h
resetVec: ;reset vector, watchdog vector, MCLR vector
pagesel startup
clrf ambient+0
clrf ambient+1 ;start off ambient at zero
bra startup ;configure peripherals
;------------------------------------------------------
;subroutines:
;24-bit cnt contains a mesurement of light level. If cnt > ambient then
;the measurement was darker than threshold - so LED should remain off.
;If cnt < ambient, LED has seen a higher light level. So turn it ON for
;about a second. Then continue with repeated measurements.
threshold:
movf ambient+2,w
subwf cnt+2,w ;compare most-sig (cnt-ambient)
skpz
return ;comparison complete, status flags show result
movf ambient+1,w
subwf cnt+1,w
skpz
return ;comparison complete, status flags show result
movf ambient+0,w
subwf cnt+1,w
return ;comparison complete, status flags show result
delayarc: ;delay up to 193 us. W has delay value
clrf cnt+1 ;ensure 24-bit cnt ends up "0"
clrf cnt+2
delay: ;accept a delay count in W, delay by current instruction-
movwf cnt+0 ;rate / 3. (loop time is 3 instructions). This is
decfsz cnt+0,f ;a blocking-type subroutine
bra $-1
return
lightup: ;turn on LED for about 1 second.
banksel LATA
movlw 0x17 ;preset anode HI, cathode LOW to turn LED ON.
movwf LATA
banksel TRISA ;both pin3 & pin4 OUTPUT (RA0, RA1, RA2 as well).
clrf TRISA ;at this point LED turns ON.
movlw 21
movwf cnt+1
clrw ;maximum delay (193 us)
luil:
call delay
decfsz cnt+2,f ;maximum delay
bra luil
decfsz cnt+1,f
bra luil ;falling thru, LED goes off, capacitor discharges:
discharge: ;discharge capacitor, LED anode off at 0V
banksel LATA
movlw 0x27 ;preset anode LOW, cathode HIGH. LED reverse-biased. RA0 hi.
movwf LATA
movlw 0x00 ;make both (pin3) & (pin4) OUTPUTS, RA0, RA1, RA2 as well.
banksel TRISA
movwf TRISA ;here's the cap discharge, LED anode to GND(Vss).on RA4
movlw 40 ;wait a bit to ensure capacitor is discharged to 0V
call delayarc ;with 16MHz INTRC clock, this delay takes about 32 us.
movlw 0x17 ;switch RA4 to INPUT, so capacitor can charge up
movwf TRISA ;note that RA4 input has TTL threshold. RA0 floats (low).
banksel PORTA ;monitor LED anode voltage until it goes HIGH.
clrf TMR0 ;reset TMR0 to 0.
bcf INTCON,2 ;ensure TMR0 overflow flag is reset too.
cntlp:
btfsc PORTA,4 ;when capacitor is charged, save the count.
bra savecnt
btfss INTCON,2 ;has TMR0 interrupt flag set?
bra cntlp
bcf INTCON,2 ;yes, reset it, then increment high-order 16 bit counter.
incf cnt+1,f
skpz
bra cntlp
incf cnt+2,f
bra cntlp
savecnt: ;capacitor has charged up to TTL threshold
movf TMR0,w ;get lowest 8-bits of count
movwf cnt+0
return ;24-bit unsigned count (little-endian) saved in cnt.
;------------------------------------------------------
startup: ;configure FOSC to 16 MHz internal RC osc (good 'nuf)
banksel OSCCON
movlw 0x78
movwf OSCCON ;speed up to 16 MHz Fosc (4 MIPS)
banksel WPUA
clrf WPUA ;turn off weak pull-ups pedantic(OPTION_REG default is OFF)
banksel ANSELA
clrf ANSELA ;force all I/O to be digital, not analog
banksel OPTION_REG ;configure 8-bit TMR0. Clk_source is FOSC/4 (4MHz)
movlw 0xD8 ;prescaler not used (1:1) 3 prescaler rate bits unused.
movwf OPTION_REG ;TMR0 starts counting
bcf INTCON,2 ;ensure TMR0 overflow flag reset. GIE remains off.
ambsetup:
call lightup ;turn on LED (alive indicator), then make a measurement
movf cnt+0,w ;of ambient light level (24-bit). Save it into "ambient"
movwf ambient+0
movf cnt+1,w
movwf ambient+1
movf cnt+2,w
movwf ambient+2
asrf cnt+2,f ;divide cnt by 8 (shift right 3 times)
rrf cnt+1,f
rrf cnt+0,f
asrf cnt+2,f
rrf cnt+1,f
rrf cnt+0,f
asrf cnt+2,f
rrf cnt+1,f
rrf cnt+0,f
movf cnt+0,w ;reduce ambient 0.875. This becomes threshold.
subwf ambient+0,f ;a new measurement will be compared against this
movf cnt+1,w ;threshold. If the count is LOWER, then LED has
subwfb ambient+1,f ;seen a brighter light than ambient. So we'd light up.
movf cnt+2,w
subwfb ambient+2,f
mainloop:
call discharge ;ensure LED is off, discharge capacitor, start counting.
call threshold ;do threshold comparison (cnt - threshold)
skpc ;decide if cnt < threshold
call lightup ;yes: light LED for about a second...
bra mainloop ; no: don't light LED, repeat measurment.
;------------------------------------------------------
END resetVec