"""
Ceiling IR LED carrier - epoxied to the lid underside. my blue line:
    rear LED (Y=150) -> bridge down the centre -> front LED (Y=70, junction
    well) -> right angle ACROSS to X=68 -> forward toward the hinge, ending
    10 mm behind the bay, above the wire tube.
Lipped U-channels throughout (closed base, lips on the glue side).
Local frame as printed/glued: x = X, y = -Y, Z=0 glue face, +Z down.
Run: python carrier.py
"""
from pathlib import Path
from build123d import *
import params as P

OUT = Path(__file__).resolve().parent.parent / "out"; OUT.mkdir(exist_ok=True)
H = P.CARRIER_SLAB_H; YF, YR = P.SENSOR_Y; XS = P.CARRIER_SIDE_X
LED_BORE = P.LED_DIA + 2 * P.PART_CLR; FLANGE_D = P.LED_FLANGE_DIA + 0.6; FLANGE_SEAT = 1.2
BOSS_R = FLANGE_D / 2 + 1.8; LEG_W, LEG_D = 1.6, 1.5; PITCH = P.LEAD_PITCH
BR_W, BR_H, BW = P.BR_W, P.BR_H, P.BR_WALL; BR_IN = BR_W - 2 * BW; MOUTH = P.BR_MOUTH
TZ0, TZ1 = BW, BR_H - BW
RIM_Y1 = P.TRAY_Y0 + P.BAY_D - P.COVER_T - P.COVER_CLR + 2 * P.WALL     # 29.7
EXIT_END_Y = RIM_Y1 + P.CARRIER_EXIT_END_GAP                             # 39.7
H1Y0, H1Y1 = YF - P.H1_LY / 2, YF + P.H1_LY / 2
H2Y0, H2Y1 = YR - P.H2_LY / 2, YR + P.H2_LY / 2

def rect(xc, Yc, w, d, z0, z1, mode=Mode.ADD):
    with BuildSketch(Plane.XY.offset(z0)) as sk:
        with Locations((xc, -Yc)): Rectangle(w, d)
    extrude(sk.sketch, amount=z1 - z0, mode=mode)

def yrun(xc, Ya, Yb, w, z0, z1, mode=Mode.ADD):  rect(xc, (Ya + Yb) / 2, w, abs(Yb - Ya), z0, z1, mode)
def xrun(Yc, xa, xb, d, z0, z1, mode=Mode.ADD):  rect((xa + xb) / 2, Yc, abs(xb - xa), d, z0, z1, mode)

def cyl(x, Y, dia, z0, z1, mode=Mode.SUBTRACT):
    with BuildSketch(Plane.XY.offset(z0)) as sk:
        with Locations((x, -Y)): Circle(dia / 2)
    extrude(sk.sketch, amount=z1 - z0, mode=mode)

def build_carrier():
    with BuildPart() as cp:
        for (lx, ly, Yc) in ((P.H1_LX, P.H1_LY, YF), (P.H2_LX, P.H2_LY, YR)):
            with BuildSketch(Plane.XY) as sk:
                with Locations((0, -Yc)): RectangleRounded(lx, ly, 3.0)
            extrude(sk.sketch, amount=H)
        # shells
        yrun(0, H1Y1 - 1, H2Y0 + 1, BR_W, 0, BR_H)                       # bridge
        xrun(YF, P.H1_LX / 2 - 1, XS + BR_W / 2, BR_W, 0, BR_H)          # across
        yrun(XS, EXIT_END_Y, YF + BR_W / 2, BR_W, 0, BR_H)               # forward
        # troughs
        yrun(0, H1Y1 - 1.5, H2Y0 + 1.5, BR_IN, TZ0, TZ1, Mode.SUBTRACT)
        xrun(YF, P.H1_LX / 2 - 3.5, XS + BR_IN / 2, BR_IN, TZ0, TZ1, Mode.SUBTRACT)
        yrun(XS, EXIT_END_Y - 0.1, YF + BR_IN / 2, BR_IN, TZ0, TZ1, Mode.SUBTRACT)
        # lip mouths
        yrun(0, H1Y1 - 1.5, H2Y0 + 1.5, MOUTH, -0.1, TZ0 + 0.01, Mode.SUBTRACT)
        xrun(YF, P.H1_LX / 2 - 3.5, XS + MOUTH / 2, MOUTH, -0.1, TZ0 + 0.01, Mode.SUBTRACT)
        yrun(XS, EXIT_END_Y - 0.1, YF + MOUTH / 2, MOUTH, -0.1, TZ0 + 0.01, Mode.SUBTRACT)
        # junction well in the front housing (open), LED boss left standing
        rect((-BR_IN / 2 + 12) / 2, YF, 12 + BR_IN / 2, P.H1_LY - 2, -0.1, TZ1, Mode.SUBTRACT)
        cyl(0, YF, 2 * BOSS_R, 0, TZ1, Mode.ADD)
        for Yc in (YF, YR):
            cyl(0, Yc, LED_BORE, -0.1, H + 0.1); cyl(0, Yc, FLANGE_D, -0.1, FLANGE_SEAT)
        for dy in (-PITCH / 2, PITCH / 2):                                # front legs -> +X
            xrun(YF + dy, 0, BOSS_R + 0.5, LEG_W, -0.1, LEG_D, Mode.SUBTRACT)
        for dx in (-PITCH / 2, PITCH / 2):                                # rear legs -> bridge
            yrun(dx, YR, H2Y0 - 0.5, LEG_W, -0.1, LEG_D, Mode.SUBTRACT)
    return cp.part

if __name__ == "__main__":
    part = build_carrier(); bb = part.bounding_box()
    print(f"Carrier X {bb.min.X:.1f}..{bb.max.X:.1f}  box-Y {-bb.max.Y:.1f}..{-bb.min.Y:.1f}  Z {bb.min.Z:.1f}..{bb.max.Z:.1f}  vol {part.volume/1000:.1f} cm^3")
    print(f"LEDs at (0,{YF}) (0,{YR}); run across at Y={YF} to X={XS}; forward run ends Y={EXIT_END_Y:.1f}")
    export_stl(part, str(OUT / "carrier.stl")); export_step(part, str(OUT / "carrier.step"))
    print("wrote out/carrier.stl, out/carrier.step")
