"""
Mature parametric robot CONNECTOR (build123d), in the style of the text-to-cad benchmarks.

A real bracket linking one servo's output horn to the next servo's holder:
  - horn flange (z=0): 4-hole bolt circle (R7, the real ST3215 horn pattern) + center bore
  - structural beam of parametric length, with lightening holes
  - holder flange (z=L): 4 mounting holes on a rectangle
  - filleted junctions

Built canonically along +Z from 0..L (mm). Length is the free parameter.
Run with the build123d venv. __main__ exports a sample STEP+STL for review.
"""
from build123d import (
    BuildPart, BuildSketch, Plane, Locations, RectangleRounded, Circle,
    extrude, fillet, Mode, Axis, export_stl,
)

# --- parameters (mm) ---
HORN_FL = 32.0                 # horn flange, square
HOLDER_FL = (48.0, 28.0)       # holder flange, rect (w, d)
FL_T = 5.0                     # flange thickness
BEAM = (22.0, 13.0)            # beam cross-section (w, d)
HORN_BOLT_R = 7.0              # ST3215 horn bolt circle radius
HORN_BOLT_D = 2.9             # M2.5 clearance
HORN_BORE = 9.0               # output spline clearance
HOLDER_BOLT = (34.0, 18.0)    # holder mount hole rectangle
HOLDER_BOLT_D = 3.4           # M3 clearance
LIGHTEN_D = 8.0
JUNC_FILLET = 2.0
LIGHTEN_PITCH = 24.0


def make_connector(length, fillets=True, lighten=True):
    L = float(length)
    beam_len = max(L - 2 * FL_T, 2.0)
    with BuildPart() as p:
        # --- base solids ---
        with BuildSketch(Plane.XY):
            RectangleRounded(HORN_FL, HORN_FL, 4)
        extrude(amount=FL_T)
        with BuildSketch(Plane.XY.offset(FL_T)):
            RectangleRounded(*BEAM, 3)
        extrude(amount=beam_len)
        with BuildSketch(Plane.XY.offset(L - FL_T)):
            RectangleRounded(*HOLDER_FL, 4)
        extrude(amount=FL_T)

        # --- fillet the two flange/beam junctions (select edges in the junction planes) ---
        if fillets:
            jed = (p.edges().filter_by(Plane.XY.offset(FL_T))
                   + p.edges().filter_by(Plane.XY.offset(L - FL_T)))
            if jed:
                fillet(jed, JUNC_FILLET)

        # --- horn bolt circle + center bore (through horn flange) ---
        with BuildSketch(Plane.XY):
            with Locations((HORN_BOLT_R, 0), (-HORN_BOLT_R, 0), (0, HORN_BOLT_R), (0, -HORN_BOLT_R)):
                Circle(HORN_BOLT_D / 2)
            Circle(HORN_BORE / 2)
        extrude(amount=FL_T + 1, mode=Mode.SUBTRACT)

        # --- holder mount holes (through holder flange) ---
        hx, hy = HOLDER_BOLT
        with BuildSketch(Plane.XY.offset(L - FL_T - 0.5)):
            with Locations((hx / 2, hy / 2), (-hx / 2, hy / 2), (hx / 2, -hy / 2), (-hx / 2, -hy / 2)):
                Circle(HOLDER_BOLT_D / 2)
        extrude(amount=FL_T + 1, mode=Mode.SUBTRACT)

        # --- lightening holes along the beam (through the d-dimension, axis Y) ---
        if lighten and beam_len > LIGHTEN_PITCH:
            n = int((beam_len - 12) // LIGHTEN_PITCH)
            z0 = FL_T + (beam_len - (n - 1) * LIGHTEN_PITCH) / 2 if n > 1 else FL_T + beam_len / 2
            for i in range(max(n, 1)):
                z = z0 + i * LIGHTEN_PITCH
                if FL_T + 8 < z < L - FL_T - 8:
                    with BuildSketch(Plane.XZ):
                        with Locations((0, z)):
                            Circle(LIGHTEN_D / 2)
                    extrude(amount=BEAM[1], both=True, mode=Mode.SUBTRACT)
    return p.part


def gen_step():
    """Entry point for the text-to-cad `cad` skill (scripts/step). Default-length sample."""
    return make_connector(120.0)


if __name__ == "__main__":
    import sys
    L = float(sys.argv[1]) if len(sys.argv) > 1 else 120.0
    fil = "nofillet" not in sys.argv
    part = make_connector(L, fillets=fil)
    export_stl(part, "connector_sample.stl", tolerance=0.05, ascii_format=False)
    print(f"made connector L={L}  volume_mm3={round(part.volume,1)}  bbox_mm={[round(x,1) for x in tuple(part.bounding_box().size)]}")
