use bone_kernel::{
    AnalyticSurface, BooleanGap, BooleanOp, BrepEdge, BrepError, BrepFace, BrepShell, BrepSolid,
    Circle2, Curve2Kind, EdgeCurve3, ExtrudeFeature, ExtrudeOperation, ExtrudeProfile,
    IntersectionCurve, Line2, MergeResult, ProfileEdge, ProfileLoop, SurfaceIntersection, boolean,
    evaluate_extrude, intersect_surfaces,
};
use bone_types::{
    Aabb3, EdgeRole, Length, Plane3, Point2, Point3, PositiveLength, SketchEntityId, SketchId,
    Tolerance, UnitVec3, millimeter,
};
use slotmap::{Key, SlotMap};

const TOL: Tolerance = Tolerance::new(1.0e-7);

struct Ids {
    features: SlotMap<bone_types::FeatureId, ()>,
    entities: SlotMap<SketchEntityId, ()>,
}

impl Ids {
    fn new() -> Self {
        Self {
            features: SlotMap::with_key(),
            entities: SlotMap::with_key(),
        }
    }
}

fn mm(value: f64) -> Length {
    Length::new::<millimeter>(value)
}

fn line(a: Point2, b: Point2) -> Curve2Kind {
    let Ok(segment) = Line2::new(a, b, TOL) else {
        panic!("distinct endpoints");
    };
    Curve2Kind::Line(segment)
}

fn plane_at_z(z: f64) -> Plane3 {
    let Ok(plane) = Plane3::new(
        Point3::from_mm(0.0, 0.0, z),
        UnitVec3::x_axis(),
        UnitVec3::y_axis(),
        TOL,
    ) else {
        panic!("orthonormal axes");
    };
    plane
}

fn closed_loop(ids: &mut Ids, corners: &[Point2]) -> ProfileLoop {
    let count = corners.len();
    let edges = (0..count)
        .map(|index| {
            ProfileEdge::new(
                line(corners[index], corners[(index + 1) % count]),
                ids.entities.insert(()),
                ids.entities.insert(()),
            )
        })
        .collect();
    ProfileLoop::Open(edges)
}

fn rectangle(ids: &mut Ids, x0: f64, y0: f64, side: f64) -> ProfileLoop {
    rect_loop(ids, x0, y0, side, side)
}

fn rect_loop(ids: &mut Ids, x0: f64, y0: f64, width: f64, depth: f64) -> ProfileLoop {
    closed_loop(
        ids,
        &[
            Point2::from_mm(x0, y0),
            Point2::from_mm(x0 + width, y0),
            Point2::from_mm(x0 + width, y0 + depth),
            Point2::from_mm(x0, y0 + depth),
        ],
    )
}

fn ell_loop(ids: &mut Ids) -> ProfileLoop {
    closed_loop(
        ids,
        &[
            Point2::from_mm(0.0, 0.0),
            Point2::from_mm(2.0, 0.0),
            Point2::from_mm(2.0, 1.0),
            Point2::from_mm(1.0, 1.0),
            Point2::from_mm(1.0, 2.0),
            Point2::from_mm(0.0, 2.0),
        ],
    )
}

fn blind(depth: f64) -> ExtrudeFeature {
    let Ok(depth) = PositiveLength::new(mm(depth)) else {
        panic!("positive depth");
    };
    ExtrudeFeature {
        operation: ExtrudeOperation::Boss(MergeResult::Separate),
        ..ExtrudeFeature::blind(SketchId::null(), depth)
    }
}

fn box_solid(ids: &mut Ids, x0: f64, y0: f64, z0: f64, side: f64, height: f64) -> BrepSolid {
    let profile = ExtrudeProfile::new(plane_at_z(z0), vec![rectangle(ids, x0, y0, side)]);
    let extrude = ids.features.insert(());
    let Ok(solid) = evaluate_extrude(extrude, &profile, &blind(height)) else {
        panic!("box extrude builds");
    };
    solid
}

fn block(
    ids: &mut Ids,
    x0: f64,
    y0: f64,
    z0: f64,
    width: f64,
    depth: f64,
    height: f64,
) -> BrepSolid {
    let profile = ExtrudeProfile::new(plane_at_z(z0), vec![rect_loop(ids, x0, y0, width, depth)]);
    let extrude = ids.features.insert(());
    let Ok(solid) = evaluate_extrude(extrude, &profile, &blind(height)) else {
        panic!("block extrude builds");
    };
    solid
}

fn ell_solid(ids: &mut Ids, z0: f64, height: f64) -> BrepSolid {
    let profile = ExtrudeProfile::new(plane_at_z(z0), vec![ell_loop(ids)]);
    let extrude = ids.features.insert(());
    let Ok(solid) = evaluate_extrude(extrude, &profile, &blind(height)) else {
        panic!("ell extrude builds");
    };
    solid
}

fn cyl_solid(ids: &mut Ids, cx: f64, cy: f64, z0: f64, radius: f64, height: f64) -> BrepSolid {
    let Ok(disk) = Circle2::new(Point2::from_mm(cx, cy), mm(radius), TOL) else {
        panic!("positive radius");
    };
    let circle = ProfileLoop::Closed {
        curve: Curve2Kind::Circle(disk),
        curve_entity: ids.entities.insert(()),
    };
    let profile = ExtrudeProfile::new(plane_at_z(z0), vec![circle]);
    let extrude = ids.features.insert(());
    let Ok(solid) = evaluate_extrude(extrude, &profile, &blind(height)) else {
        panic!("cylinder extrude builds");
    };
    solid
}

fn holed_box_solid(
    ids: &mut Ids,
    x0: f64,
    y0: f64,
    z0: f64,
    side: f64,
    height: f64,
    hole: (f64, f64, f64),
) -> BrepSolid {
    let (cx, cy, radius) = hole;
    let outer = rect_loop(ids, x0, y0, side, side);
    let Ok(disk) = Circle2::new(Point2::from_mm(cx, cy), mm(radius), TOL) else {
        panic!("positive radius");
    };
    let hole = ProfileLoop::Closed {
        curve: Curve2Kind::Circle(disk),
        curve_entity: ids.entities.insert(()),
    };
    let profile = ExtrudeProfile::new(plane_at_z(z0), vec![outer, hole]);
    let extrude = ids.features.insert(());
    let Ok(solid) = evaluate_extrude(extrude, &profile, &blind(height)) else {
        panic!("holed box extrude builds");
    };
    solid
}

fn revolve_tube(ids: &mut Ids, r_inner: f64, r_outer: f64, z0: f64, z1: f64) -> BrepSolid {
    use bone_kernel::{ResolvedRevolve, evaluate_revolve};
    use bone_types::Axis3;
    let corners = [
        Point2::from_mm(r_inner, z0),
        Point2::from_mm(r_outer, z0),
        Point2::from_mm(r_outer, z1),
        Point2::from_mm(r_inner, z1),
    ];
    let Ok(xz) = Plane3::new(
        Point3::origin(),
        UnitVec3::x_axis(),
        UnitVec3::z_axis(),
        TOL,
    ) else {
        panic!("xz plane");
    };
    let profile = ExtrudeProfile::new(xz, vec![closed_loop(ids, &corners)]);
    let plan = ResolvedRevolve {
        axis: Axis3::new(Point3::origin(), UnitVec3::z_axis()),
        forward_rad: core::f64::consts::TAU,
        backward_rad: 0.0,
        thin: None,
    };
    let Ok(solid) = evaluate_revolve(ids.features.insert(()), &profile, &plan) else {
        panic!("revolve tube builds");
    };
    solid
}

#[test]
fn a_revolved_tube_extracts_into_the_boolean_pipeline() {
    let mut ids = Ids::new();
    let tube = revolve_tube(&mut ids, 2.0, 3.0, 1.0, 4.0);
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let Ok(merged) = boolean(&base, &tube, BooleanOp::Union, TOL) else {
        panic!("a revolved tube merges into its host through the surface-extracted pipeline");
    };
    assert!(merged.validate(TOL).is_ok());
    assert_eq!(
        merged.iter_faces().count(),
        6,
        "a boss fully inside its host is absorbed into the host box"
    );
}

#[test]
fn a_box_cut_into_a_holed_box_keeps_the_round_hole() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = holed_box_solid(&mut ids, 0.0, 0.0, 0.0, 6.0, 4.0, (3.0, 3.0, 1.0));
    let tool = block(&mut ids, 5.0, -1.0, -1.0, 2.0, 8.0, 6.0);
    let carved = match boolean(&base, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a slab cut spares the round hole: {error:?}"),
    };
    assert!(
        carved.validate(TOL).is_ok(),
        "the carved holed box is closed"
    );
    assert!(is_manifold(&carved), "the carved holed box is 2-manifold");
    let expected = (6.0 * 6.0 * 4.0 - PI * 1.0 * 1.0 * 4.0) - 1.0 * 6.0 * 4.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-2,
        "holed box loses a slab, keeps the round bore: got {}, want {expected}",
        mesh_volume(&carved),
    );
    assert!(
        carved
            .iter_edges()
            .any(|edge| matches!(edge.curve(), EdgeCurve3::Circle(_) | EdgeCurve3::Arc(_))),
        "the surviving round bore keeps arc rims",
    );
}

#[test]
fn a_holed_box_cut_is_byte_identical_across_rebuilds() {
    let mut ids = Ids::new();
    let base = holed_box_solid(&mut ids, 0.0, 0.0, 0.0, 6.0, 4.0, (3.0, 3.0, 1.0));
    let tool = block(&mut ids, 5.0, -1.0, -1.0, 2.0, 8.0, 6.0);
    let Ok(first) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("first carve");
    };
    let Ok(second) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("second carve");
    };
    assert_eq!(
        first.content_key().bytes(),
        second.content_key().bytes(),
        "a holed-box cut rebuilds byte-identically",
    );
}

#[test]
fn a_box_milled_into_a_cylinder_leaves_a_flat() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let stock = cyl_solid(&mut ids, 0.0, 0.0, 0.0, 3.0, 5.0);
    let tool = block(&mut ids, 1.0, -4.0, -1.0, 7.0, 8.0, 7.0);
    let carved = match boolean(&stock, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a box mills a flat onto the cylinder side: {error:?}"),
    };
    assert!(
        carved.validate(TOL).is_ok(),
        "the milled cylinder is closed"
    );
    assert!(is_manifold(&carved), "the milled cylinder is 2-manifold");
    let (xlo, xhi) = x_span(&carved);
    assert!(
        (xlo + 3.0).abs() <= 1.0e-4 && (xhi - 1.0).abs() <= 1.0e-4,
        "the flat lands at x=1, got {xlo}..{xhi}",
    );
    let segment = 9.0 * (1.0_f64 / 3.0).acos() - (8.0_f64).sqrt();
    let expected = PI * 9.0 * 5.0 - segment * 5.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-1,
        "the cylinder loses the x>1 segment: got {}, want {expected}",
        mesh_volume(&carved),
    );
    assert!(
        carved
            .iter_edges()
            .any(|edge| matches!(edge.curve(), EdgeCurve3::Arc(_) | EdgeCurve3::Circle(_))),
        "the milled cylinder keeps arc rims",
    );
}

#[test]
fn coaxial_cylinders_intersect_in_the_overlap() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let lower = cyl_solid(&mut ids, 0.0, 0.0, 0.0, 3.0, 5.0);
    let upper = cyl_solid(&mut ids, 0.0, 0.0, 2.0, 3.0, 5.0);
    let common = match boolean(&lower, &upper, BooleanOp::Intersection, TOL) {
        Ok(common) => common,
        Err(error) => panic!("two coaxial cylinders meet in their overlap: {error:?}"),
    };
    assert!(
        common.validate(TOL).is_ok(),
        "the overlap is a closed solid"
    );
    assert!(is_manifold(&common), "the overlap is 2-manifold");
    let (lo, hi) = z_span(&common);
    assert!(
        (lo - 2.0).abs() <= 1.0e-5 && (hi - 5.0).abs() <= 1.0e-5,
        "the overlap spans the shared z range, got {lo}..{hi}",
    );
    let expected = PI * 3.0 * 3.0 * 3.0;
    assert!(
        (mesh_volume(&common) - expected).abs() <= 1.0e-1,
        "the overlap is a shorter cylinder: got {}, want {expected}",
        mesh_volume(&common),
    );
}

#[test]
fn coaxial_cylinder_intersection_is_byte_identical() {
    let mut ids = Ids::new();
    let lower = cyl_solid(&mut ids, 0.0, 0.0, 0.0, 3.0, 5.0);
    let upper = cyl_solid(&mut ids, 0.0, 0.0, 2.0, 3.0, 5.0);
    let Ok(first) = boolean(&lower, &upper, BooleanOp::Intersection, TOL) else {
        panic!("first intersect");
    };
    let Ok(second) = boolean(&lower, &upper, BooleanOp::Intersection, TOL) else {
        panic!("second intersect");
    };
    assert_eq!(
        first.content_key().bytes(),
        second.content_key().bytes(),
        "coaxial cylinder intersection rebuilds byte-identically",
    );
}

fn frame_solid(
    ids: &mut Ids,
    x0: f64,
    y0: f64,
    z0: f64,
    outer: f64,
    inner: f64,
    height: f64,
) -> BrepSolid {
    let margin = (outer - inner) / 2.0;
    let outer_loop = rect_loop(ids, x0, y0, outer, outer);
    let inner_loop = rect_loop(ids, x0 + margin, y0 + margin, inner, inner);
    let profile = ExtrudeProfile::new(plane_at_z(z0), vec![outer_loop, inner_loop]);
    let extrude = ids.features.insert(());
    let Ok(solid) = evaluate_extrude(extrude, &profile, &blind(height)) else {
        panic!("frame extrude builds");
    };
    solid
}

#[test]
fn a_frame_prism_has_a_holed_cap() {
    let mut ids = Ids::new();
    let frame = frame_solid(&mut ids, 0.0, 0.0, 0.0, 6.0, 2.0, 4.0);
    assert!(frame.validate(TOL).is_ok(), "the frame is a closed solid");
    assert!(
        frame.iter_faces().any(|face| face.loops().len() >= 2),
        "the frame cap is a single face carrying an inner loop",
    );
    assert!(
        (mesh_volume(&frame) - (6.0 * 6.0 - 2.0 * 2.0) * 4.0).abs() <= 1.0e-4,
        "the frame volume is the outer square less the square hole",
    );
}

#[test]
fn a_box_cut_into_a_holed_base_carves_a_pocket() {
    let mut ids = Ids::new();
    let frame = frame_solid(&mut ids, 0.0, 0.0, 0.0, 6.0, 2.0, 4.0);
    let tool = box_solid(&mut ids, 0.0, 0.0, -1.0, 1.0, 6.0);
    let Ok(carved) = boolean(&frame, &tool, BooleanOp::Difference, TOL) else {
        panic!("a box bores through a corner of the holed frame base");
    };
    assert!(carved.validate(TOL).is_ok(), "the carved frame is closed");
    assert!(is_manifold(&carved), "the carved frame is 2-manifold");
    assert!(
        (mesh_volume(&carved) - ((6.0 * 6.0 - 2.0 * 2.0) * 4.0 - 1.0 * 1.0 * 4.0)).abs() <= 1.0e-4,
        "the frame loses a unit through-column: got {}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_frame_tool_carves_a_square_moat() {
    let mut ids = Ids::new();
    let stock = box_solid(&mut ids, 0.0, 0.0, 0.0, 8.0, 4.0);
    let tool = frame_solid(&mut ids, 1.0, 1.0, 2.0, 6.0, 2.0, 5.0);
    let Ok(carved) = boolean(&stock, &tool, BooleanOp::Difference, TOL) else {
        panic!("a holed frame tool carves a square moat into the stock");
    };
    assert!(carved.validate(TOL).is_ok(), "the moated block is closed");
    assert!(is_manifold(&carved), "the moated block is 2-manifold");
    assert!(
        (mesh_volume(&carved) - (8.0 * 8.0 * 4.0 - (6.0 * 6.0 - 2.0 * 2.0) * 2.0)).abs() <= 1.0e-4,
        "the stock loses a frame-shaped pocket two deep: got {}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_blind_circle_cut_carves_a_round_hole() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, 0.0, 0.0, 0.0, 6.0, 6.0, 4.0);
    let tool = cyl_solid(&mut ids, 3.0, 3.0, 1.0, 1.0, 4.0);
    let carved = match boolean(&base, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a cylinder carves a round blind hole: {error:?}"),
    };
    assert!(
        carved.validate(TOL).is_ok(),
        "the carved body is a closed solid"
    );
    assert!(is_manifold(&carved), "the carved body is 2-manifold");
    let expected = 6.0 * 6.0 * 4.0 - PI * 1.0 * 1.0 * 3.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-2,
        "block loses a pi r squared depth plug: got {}, want {expected}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_through_circle_cut_carves_a_round_hole() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, 0.0, 0.0, 0.0, 6.0, 6.0, 4.0);
    let tool = cyl_solid(&mut ids, 3.0, 3.0, -1.0, 1.0, 6.0);
    let carved = match boolean(&base, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a cylinder bores a round through-hole: {error:?}"),
    };
    assert!(
        carved.validate(TOL).is_ok(),
        "the bored body is a closed solid"
    );
    assert!(is_manifold(&carved), "the bored body is 2-manifold");
    let expected = 6.0 * 6.0 * 4.0 - PI * 1.0 * 1.0 * 4.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-2,
        "block loses a full-height plug: got {}, want {expected}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_circle_cut_is_byte_identical_across_rebuilds() {
    let mut ids = Ids::new();
    let base = block(&mut ids, 0.0, 0.0, 0.0, 6.0, 6.0, 4.0);
    let tool = cyl_solid(&mut ids, 3.0, 3.0, 1.0, 1.0, 4.0);
    let first = match boolean(&base, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("first carve: {error:?}"),
    };
    let second = match boolean(&base, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("second carve: {error:?}"),
    };
    assert_eq!(
        first.content_key().bytes(),
        second.content_key().bytes(),
        "a circle cut rebuilds byte-identically",
    );
}

#[test]
fn a_circle_cut_keeps_the_rim_as_a_true_arc() {
    let mut ids = Ids::new();
    let base = block(&mut ids, 0.0, 0.0, 0.0, 6.0, 6.0, 4.0);
    let tool = cyl_solid(&mut ids, 3.0, 3.0, 1.0, 1.0, 4.0);
    let Ok(carved) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("carve builds");
    };
    let arcs = carved
        .iter_edges()
        .filter(|edge| matches!(edge.curve(), EdgeCurve3::Arc(_) | EdgeCurve3::Circle(_)))
        .count();
    assert!(
        arcs >= 4,
        "the round hole keeps its rim as exact arcs, got {arcs}",
    );
}

#[test]
fn a_circle_cut_lowers_a_revolved_wall_to_step() {
    let mut ids = Ids::new();
    let base = block(&mut ids, 0.0, 0.0, 0.0, 6.0, 6.0, 4.0);
    let tool = cyl_solid(&mut ids, 3.0, 3.0, 1.0, 1.0, 4.0);
    let Ok(carved) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("carve builds");
    };
    let Ok(text) = carved.to_step_body() else {
        panic!("a carved body lowers to STEP");
    };
    eprintln!(
        "step surfaces: cyl={} rev={}",
        text.contains("CYLINDRICAL_SURFACE"),
        text.contains("SURFACE_OF_REVOLUTION"),
    );
    assert!(
        text.contains("CYLINDRICAL_SURFACE") || text.contains("SURFACE_OF_REVOLUTION"),
        "the round wall lowers to an analytic curved surface",
    );
}

#[test]
fn a_circle_crossing_the_edge_is_reported_not_faked() {
    let mut ids = Ids::new();
    let base = block(&mut ids, 0.0, 0.0, 0.0, 6.0, 6.0, 4.0);
    let tool = cyl_solid(&mut ids, 5.7, 3.0, 1.0, 1.0, 4.0);
    assert!(
        matches!(
            boolean(&base, &tool, BooleanOp::Difference, TOL),
            Err(BrepError::BooleanUnsupported {
                detail: BooleanGap::PartialCircleImprint
            }),
        ),
        "a circle poking past the face edge is gated, not silently mis-cut",
    );
}

fn z_span(solid: &BrepSolid) -> (f64, f64) {
    let Some(bbox): Option<Aabb3> = solid.bounding_box() else {
        panic!("solid has a bounding box");
    };
    let (_, _, lo) = bbox.min().coords_mm();
    let (_, _, hi) = bbox.max().coords_mm();
    (lo, hi)
}

#[test]
fn stacked_boxes_union_is_one_taller_body() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let boss = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let merged = match boolean(&base, &boss, BooleanOp::Union, TOL) {
        Ok(merged) => merged,
        Err(error) => panic!("stacked boxes union into one body: {error:?}"),
    };
    assert!(merged.validate(TOL).is_ok(), "union is a closed solid");
    let (lo, hi) = z_span(&merged);
    assert!((lo - 0.0).abs() <= 1.0e-5);
    assert!((hi - 2.0).abs() <= 1.0e-5);
    assert_eq!(merged.iter_shells().count(), 1);
    assert!(
        merged
            .iter_edges()
            .any(|edge| matches!(edge.label().role, EdgeRole::Intersection { .. })),
        "the merge seam carries an intersection edge role"
    );
}

#[test]
fn nested_boxes_difference_carves_a_void() {
    let mut ids = Ids::new();
    let outer = box_solid(&mut ids, 0.0, 0.0, 0.0, 3.0, 3.0);
    let inner = box_solid(&mut ids, 1.0, 1.0, 1.0, 1.0, 1.0);
    let Ok(carved) = boolean(&outer, &inner, BooleanOp::Difference, TOL) else {
        panic!("subtracting an interior box carves a void");
    };
    assert!(carved.validate(TOL).is_ok(), "difference is a valid solid");
    assert_eq!(carved.iter_faces().count(), 12);
    assert_eq!(carved.iter_shells().count(), 2);
}

#[test]
fn nested_boxes_intersection_is_the_inner_box() {
    let mut ids = Ids::new();
    let outer = box_solid(&mut ids, 0.0, 0.0, 0.0, 3.0, 3.0);
    let inner = box_solid(&mut ids, 1.0, 1.0, 1.0, 1.0, 1.0);
    let Ok(common) = boolean(&outer, &inner, BooleanOp::Intersection, TOL) else {
        panic!("the intersection is the inner box");
    };
    assert!(common.validate(TOL).is_ok());
    assert_eq!(common.iter_faces().count(), 6);
    let (lo, hi) = z_span(&common);
    assert!((lo - 1.0).abs() <= 1.0e-5);
    assert!((hi - 2.0).abs() <= 1.0e-5);
}

fn is_manifold(solid: &BrepSolid) -> bool {
    solid
        .iter_edges()
        .all(|edge| solid.adjacent_faces(edge.id()).len() == 2)
}

#[test]
fn a_corner_overlap_union_is_one_manifold_body() {
    let mut ids = Ids::new();
    let a = box_solid(&mut ids, 0.0, 0.0, 0.0, 2.0, 2.0);
    let b = box_solid(&mut ids, 1.0, 1.0, 1.0, 2.0, 2.0);
    let Ok(union) = boolean(&a, &b, BooleanOp::Union, TOL) else {
        panic!("two corner-overlapping cubes union into one body");
    };
    assert!(union.validate(TOL).is_ok());
    assert_eq!(
        union.iter_shells().count(),
        1,
        "the overlap fuses into one body"
    );
    assert!(is_manifold(&union), "every edge bounds exactly two faces");
    assert!(
        (mesh_volume(&union) - 15.0).abs() <= 1.0e-6,
        "eight plus eight less the shared unit corner",
    );
}

#[test]
fn a_through_pocket_cut_carves_a_square_hole() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 2.0, 1.0);
    let tool = box_solid(&mut ids, 0.5, 0.5, -1.0, 1.0, 3.0);
    let Ok(carved) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("a prism through the slab carves a square through-hole");
    };
    assert!(carved.validate(TOL).is_ok());
    assert_eq!(carved.iter_shells().count(), 1);
    assert!(is_manifold(&carved));
    assert!(
        (mesh_volume(&carved) - 3.0).abs() <= 1.0e-6,
        "the two-by-two slab loses a unit prism",
    );
    assert!(
        carved
            .iter_edges()
            .any(|edge| matches!(edge.label().role, EdgeRole::Intersection { .. })),
        "the hole walls meet the caps along intersection edges",
    );
}

#[test]
fn a_blind_pocket_cut_leaves_a_floor() {
    let mut ids = Ids::new();
    let stock = box_solid(&mut ids, 0.0, 0.0, 0.0, 4.0, 4.0);
    let pocket = box_solid(&mut ids, 1.0, 1.0, 2.0, 2.0, 5.0);
    let Ok(carved) = boolean(&stock, &pocket, BooleanOp::Difference, TOL) else {
        panic!("a tool stopping inside the stock carves a blind pocket");
    };
    assert!(carved.validate(TOL).is_ok());
    assert_eq!(carved.iter_shells().count(), 1);
    assert!(is_manifold(&carved));
    assert!(
        (mesh_volume(&carved) - 56.0).abs() <= 1.0e-6,
        "the four-cube stock loses a two-cube pocket above its floor",
    );
}

#[test]
fn a_boss_on_a_larger_face_unions_as_one_body() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 2.0, 1.0);
    let boss = box_solid(&mut ids, 0.5, 0.5, 1.0, 1.0, 1.0);
    let Ok(union) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("a boss inside a larger cap unions into one body");
    };
    assert!(union.validate(TOL).is_ok());
    assert_eq!(union.iter_shells().count(), 1);
    assert!(is_manifold(&union));
    assert!(
        (mesh_volume(&union) - 5.0).abs() <= 1.0e-6,
        "the four-volume base gains a unit boss",
    );
}

#[test]
fn a_reflex_tool_carves_a_reflex_pocket() {
    let mut ids = Ids::new();
    let stock = box_solid(&mut ids, 0.0, 0.0, 0.0, 4.0, 4.0);
    let tool = ell_solid(&mut ids, 2.0, 5.0);
    let Ok(carved) = boolean(&stock, &tool, BooleanOp::Difference, TOL) else {
        panic!("a non-convex L tool carves a reflex blind pocket");
    };
    assert!(carved.validate(TOL).is_ok(), "the pocketed block is closed");
    assert!(is_manifold(&carved), "the pocketed block is 2-manifold");
    assert!(
        (mesh_volume(&carved) - (4.0 * 4.0 * 4.0 - 3.0 * 2.0)).abs() <= 1.0e-4,
        "the stock loses an L-area-three pocket two deep: got {}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_reflex_base_takes_a_box_cut() {
    let mut ids = Ids::new();
    let ell = ell_solid(&mut ids, 0.0, 4.0);
    let tool = box_solid(&mut ids, 0.25, 0.25, -1.0, 0.5, 6.0);
    let carved = match boolean(&ell, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a box bores through the leg of a non-convex L base: {error:?}"),
    };
    assert!(carved.validate(TOL).is_ok(), "the carved L is closed");
    assert!(is_manifold(&carved), "the carved L is 2-manifold");
    assert!(
        (mesh_volume(&carved) - (3.0 * 4.0 - 0.5 * 0.5 * 4.0)).abs() <= 1.0e-4,
        "the L-prism leg loses an interior through-column: got {}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_reflex_cap_face_unions_cleanly() {
    let mut ids = Ids::new();
    let ell = ell_solid(&mut ids, 0.0, 1.0);
    let lid = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let Ok(union) = boolean(&ell, &lid, BooleanOp::Union, TOL) else {
        panic!("a reflex L-profile cap decomposes into convex cells and unions cleanly");
    };
    assert!(union.validate(TOL).is_ok(), "the union is a closed solid");
    assert_eq!(union.iter_shells().count(), 1, "one connected body");
    assert!(is_manifold(&union), "every edge bounds exactly two faces");
    assert!(
        (mesh_volume(&union) - 4.0).abs() <= 1.0e-6,
        "the L-prism of volume three gains a unit lid",
    );
}

#[test]
fn a_coplanar_cross_overlap_unions_cleanly() {
    let mut ids = Ids::new();
    let bar = block(&mut ids, 0.0, 1.0, 0.0, 3.0, 1.0, 1.0);
    let cross = block(&mut ids, 1.0, 0.0, 1.0, 1.0, 3.0, 1.0);
    let Ok(union) = boolean(&bar, &cross, BooleanOp::Union, TOL) else {
        panic!("a bar and a crossing bar sharing a coplanar contact union cleanly");
    };
    assert!(union.validate(TOL).is_ok());
    assert_eq!(union.iter_shells().count(), 1);
    assert!(is_manifold(&union));
    assert!(
        (mesh_volume(&union) - 6.0).abs() <= 1.0e-6,
        "the two bars meet along a coplanar face, no shared volume",
    );
}

#[test]
fn disjoint_intersection_is_empty() {
    let mut ids = Ids::new();
    let a = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let b = box_solid(&mut ids, 10.0, 10.0, 10.0, 1.0, 1.0);
    assert!(matches!(
        boolean(&a, &b, BooleanOp::Intersection, TOL),
        Err(BrepError::BooleanEmpty)
    ));
}

#[test]
fn disjoint_difference_reports_no_intersection() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let tool = box_solid(&mut ids, 10.0, 10.0, 10.0, 1.0, 1.0);
    assert!(matches!(
        boolean(&base, &tool, BooleanOp::Difference, TOL),
        Err(BrepError::BooleanDisjoint)
    ));
}

#[test]
fn engulfed_difference_is_empty() {
    let mut ids = Ids::new();
    let inner = box_solid(&mut ids, 1.0, 1.0, 1.0, 1.0, 1.0);
    let outer = box_solid(&mut ids, 0.0, 0.0, 0.0, 3.0, 3.0);
    assert!(matches!(
        boolean(&inner, &outer, BooleanOp::Difference, TOL),
        Err(BrepError::BooleanEmpty)
    ));
}

#[test]
fn original_edge_roles_survive_a_union() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let boss = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let Ok(merged) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("union builds");
    };
    let roles: Vec<EdgeRole> = merged.iter_edges().map(|edge| edge.label().role).collect();
    assert!(
        roles
            .iter()
            .any(|role| matches!(role, EdgeRole::Intersection { .. })),
        "the merge seam carries an intersection edge role",
    );
    assert!(
        roles
            .iter()
            .any(|role| !matches!(role, EdgeRole::Intersection { .. })),
        "edges away from the seam keep their original cap and side roles",
    );
}

#[test]
fn ssi_predicts_a_realized_merge_generator() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let boss = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let Ok(merged) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("union builds");
    };

    let origin = Point3::from_mm(0.0, 0.0, 0.0);
    let Ok(neg_y) = UnitVec3::try_from_components(0.0, -1.0, 0.0, TOL) else {
        panic!("unit normal");
    };
    let Ok(neg_x) = UnitVec3::try_from_components(-1.0, 0.0, 0.0, TOL) else {
        panic!("unit normal");
    };
    let front = AnalyticSurface::Plane {
        origin,
        normal: neg_y,
    };
    let left = AnalyticSurface::Plane {
        origin,
        normal: neg_x,
    };
    let SurfaceIntersection::Curves(curves) = intersect_surfaces(front, left, TOL) else {
        panic!("two adjacent side planes meet in a generator line");
    };
    let [IntersectionCurve::Line(line)] = curves.as_slice() else {
        panic!("a single generator line");
    };
    let (px, py, _) = line.point().coords_mm();
    let (dx, dy, dz) = line.direction().components();
    assert!(
        px.abs() <= 1.0e-9 && py.abs() <= 1.0e-9,
        "generator at x=0, y=0"
    );
    assert!(
        dx.abs() <= 1.0e-9 && dy.abs() <= 1.0e-9 && dz.abs() > 0.99,
        "the generator runs vertically",
    );
    assert!(
        merged.iter_vertices().any(|vertex| {
            let (x, y, z) = vertex.position().coords_mm();
            x.abs() <= 1.0e-6 && y.abs() <= 1.0e-6 && (z - 1.0).abs() <= 1.0e-6
        }),
        "the union realizes a seam vertex on the SSI generator",
    );
}

#[test]
fn ssi_generators_match_every_union_seam() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let boss = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let Ok(merged) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("union builds");
    };

    let normal = |x: f64, y: f64, z: f64| {
        let Ok(unit) = UnitVec3::try_from_components(x, y, z, TOL) else {
            panic!("unit normal");
        };
        unit
    };
    let plane = |x: f64, y: f64, z: f64, n: UnitVec3| AnalyticSurface::Plane {
        origin: Point3::from_mm(x, y, z),
        normal: n,
    };
    let front = plane(0.0, 0.0, 0.0, normal(0.0, -1.0, 0.0));
    let back = plane(0.0, 1.0, 0.0, normal(0.0, 1.0, 0.0));
    let left = plane(0.0, 0.0, 0.0, normal(-1.0, 0.0, 0.0));
    let right = plane(1.0, 0.0, 0.0, normal(1.0, 0.0, 0.0));

    [
        (front, left, 0.0, 0.0),
        (front, right, 1.0, 0.0),
        (back, right, 1.0, 1.0),
        (back, left, 0.0, 1.0),
    ]
    .into_iter()
    .for_each(|(a, b, ex, ey)| {
        let SurfaceIntersection::Curves(curves) = intersect_surfaces(a, b, TOL) else {
            panic!("adjacent side planes meet in a generator");
        };
        let [IntersectionCurve::Line(line)] = curves.as_slice() else {
            panic!("a single vertical generator");
        };
        let (px, py, _) = line.point().coords_mm();
        let (dx, dy, dz) = line.direction().components();
        assert!(
            (px - ex).abs() <= 1.0e-9 && (py - ey).abs() <= 1.0e-9,
            "generator sits over the seam corner",
        );
        assert!(
            dx.abs() <= 1.0e-9 && dy.abs() <= 1.0e-9 && dz.abs() > 0.99,
            "generator runs vertically",
        );
        let realized = |z: f64| {
            merged.iter_vertices().any(|vertex| {
                let (vx, vy, vz) = vertex.position().coords_mm();
                (vx - ex).abs() <= 1.0e-6 && (vy - ey).abs() <= 1.0e-6 && (vz - z).abs() <= 1.0e-6
            })
        };
        assert!(
            realized(0.0) && realized(2.0),
            "the union realizes the full generator edge at this corner",
        );
    });
}

fn edge_role_fingerprint(solid: &BrepSolid) -> Vec<String> {
    let mut roles: Vec<String> = solid
        .iter_edges()
        .map(|edge| format!("{:?}", edge.label().role))
        .collect();
    roles.sort();
    roles
}

fn geometry_fingerprint(solid: &BrepSolid) -> (usize, usize, Vec<(String, String, String)>) {
    let mut vertices: Vec<(String, String, String)> = solid
        .iter_vertices()
        .map(|vertex| {
            let (x, y, z) = vertex.position().coords_mm();
            (format!("{x:.4}"), format!("{y:.4}"), format!("{z:.4}"))
        })
        .collect();
    vertices.sort();
    (
        solid.iter_faces().count(),
        solid.iter_shells().count(),
        vertices,
    )
}

proptest::proptest! {
    #[test]
    fn difference_distributes_over_union(
        left in 1u32..=4,
        tool_width in 1u32..=4,
        right in 1u32..=4,
        front in 1u32..=4,
        tool_depth in 1u32..=4,
        back in 1u32..=4,
        floor in 1u32..=4,
        lower_height in 1u32..=4,
        upper_height in 1u32..=4,
        ceiling in 1u32..=4,
    ) {
        let mut ids = Ids::new();
        let span = f64::from;
        let outer_width = span(left + tool_width + right);
        let outer_depth = span(front + tool_depth + back);
        let outer_height = span(floor + lower_height + upper_height + ceiling);
        let whole = block(&mut ids, 0.0, 0.0, 0.0, outer_width, outer_depth, outer_height);
        let lower = block(
            &mut ids,
            span(left),
            span(front),
            span(floor),
            span(tool_width),
            span(tool_depth),
            span(lower_height),
        );
        let upper = block(
            &mut ids,
            span(left),
            span(front),
            span(floor + lower_height),
            span(tool_width),
            span(tool_depth),
            span(upper_height),
        );

        let step = boolean(&whole, &lower, BooleanOp::Difference, TOL)
            .and_then(|partial| boolean(&partial, &upper, BooleanOp::Difference, TOL));
        let combined = boolean(&lower, &upper, BooleanOp::Union, TOL)
            .and_then(|tool| boolean(&whole, &tool, BooleanOp::Difference, TOL));
        let (Ok(step), Ok(combined)) = (step, combined) else {
            panic!("separable a - b - c and a - (b union c) both build");
        };

        proptest::prop_assert_eq!(
            geometry_fingerprint(&step),
            geometry_fingerprint(&combined),
        );
    }
}

fn shell_reach(solid: &BrepSolid, shell: &BrepShell) -> f64 {
    use std::collections::HashMap;
    let faces: HashMap<_, _> = solid.iter_faces().map(|face| (face.id(), face)).collect();
    let loops: HashMap<_, _> = solid.iter_loops().map(|item| (item.id(), item)).collect();
    let edges: HashMap<_, _> = solid.iter_edges().map(|edge| (edge.id(), edge)).collect();
    let vertices: HashMap<_, _> = solid
        .iter_vertices()
        .map(|vertex| (vertex.id(), vertex.position()))
        .collect();
    shell
        .faces()
        .iter()
        .filter_map(|face| faces.get(face))
        .flat_map(|face| face.loops())
        .filter_map(|item| loops.get(item))
        .flat_map(|item| item.edges())
        .filter_map(|edge| edges.get(edge))
        .flat_map(|edge| edge.vertices())
        .filter_map(|vertex| vertices.get(&vertex))
        .map(|position| {
            let (x, y, z) = position.coords_mm();
            x.abs().max(y.abs()).max(z.abs())
        })
        .fold(0.0_f64, f64::max)
}

#[test]
fn voided_difference_lists_the_outer_shell_first() {
    let mut ids = Ids::new();
    let inner = box_solid(&mut ids, 1.0, 1.0, 1.0, 1.0, 1.0);
    let outer = box_solid(&mut ids, 0.0, 0.0, 0.0, 3.0, 3.0);
    let Ok(carved) = boolean(&outer, &inner, BooleanOp::Difference, TOL) else {
        panic!("subtracting an interior box carves a void");
    };
    let shells: Vec<&BrepShell> = carved.iter_shells().collect();
    let [exterior, void] = shells.as_slice() else {
        panic!("a voided solid has an outer shell and one cavity");
    };
    let exterior_reach = shell_reach(&carved, exterior);
    let void_reach = shell_reach(&carved, void);
    assert!(
        (exterior_reach - 3.0).abs() <= 1.0e-6,
        "the first shell reaches the outer corner",
    );
    assert!(
        exterior_reach > void_reach,
        "the enclosing shell sorts ahead of the cavity it contains",
    );
    let Ok(text) = carved.to_step_body() else {
        panic!("a voided solid lowers to STEP");
    };
    assert!(
        text.contains("BREP_WITH_VOIDS"),
        "the cavity is written as a void, not a second outer body",
    );
}

#[test]
fn union_result_exports_to_step() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let boss = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let Ok(merged) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("union builds");
    };
    let body = merged.to_step_body();
    assert!(
        body.is_ok_and(|text| text.contains("MANIFOLD_SOLID_BREP")),
        "a boolean result lowers to a STEP solid body"
    );
}

#[test]
fn boolean_is_deterministic() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let boss = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let Ok(first) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("union builds");
    };
    let Ok(second) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("union builds");
    };
    let labels_first: Vec<_> = first.iter_faces().map(BrepFace::label).collect();
    let labels_second: Vec<_> = second.iter_faces().map(BrepFace::label).collect();
    assert_eq!(
        labels_first, labels_second,
        "face order is canonical by label"
    );
    assert_eq!(
        geometry_fingerprint(&first),
        geometry_fingerprint(&second),
        "vertices, face count, and shell count are stable",
    );
    assert_eq!(
        edge_role_fingerprint(&first),
        edge_role_fingerprint(&second),
        "edge roles are stable across runs",
    );
}

#[test]
fn every_manifold_edge_indexes_exactly_two_faces() {
    let mut ids = Ids::new();
    let solid = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    solid.iter_edges().for_each(|edge| {
        assert_eq!(
            solid.adjacent_faces(edge.id()).len(),
            2,
            "{} bounds two faces in a closed manifold",
            edge.label(),
        );
    });
}

#[test]
fn intersection_edges_rederive_from_their_two_faces() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 1.0, 1.0);
    let boss = box_solid(&mut ids, 0.0, 0.0, 1.0, 1.0, 1.0);
    let Ok(merged) = boolean(&base, &boss, BooleanOp::Union, TOL) else {
        panic!("union builds");
    };
    let seams: Vec<_> = merged
        .iter_edges()
        .filter(|edge| matches!(edge.label().role, EdgeRole::Intersection { .. }))
        .map(BrepEdge::id)
        .collect();
    assert!(!seams.is_empty(), "the union carries intersection edges");
    seams.iter().for_each(|edge| {
        let faces = merged.adjacent_faces(*edge);
        let [a, b] = faces else {
            panic!(
                "a seam edge bounds exactly two faces, found {}",
                faces.len()
            );
        };
        let derived: Vec<_> = merged.edges_between(*a, *b).map(BrepEdge::id).collect();
        assert_eq!(
            derived.as_slice(),
            &[*edge],
            "the seam edge re-derives uniquely by intersecting the two faces it bounds",
        );
    });
}

fn x_span(solid: &BrepSolid) -> (f64, f64) {
    let Some(bbox): Option<Aabb3> = solid.bounding_box() else {
        panic!("solid has a bounding box");
    };
    let (lo, _, _) = bbox.min().coords_mm();
    let (hi, _, _) = bbox.max().coords_mm();
    (lo, hi)
}

fn trim_solids(ids: &mut Ids) -> (BrepSolid, BrepSolid) {
    let base = box_solid(ids, 0.0, 0.0, 0.0, 10.0, 10.0);
    let tool = block(ids, 7.0, -1.0, -1.0, 5.0, 12.0, 12.0);
    (base, tool)
}

#[test]
fn a_traversing_cut_trims_the_solid_to_a_single_body() {
    let mut ids = Ids::new();
    let (base, tool) = trim_solids(&mut ids);
    let Ok(carved) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("a tool that traverses the body in y and z trims one face off each side");
    };

    assert!(
        carved.validate(TOL).is_ok(),
        "the trimmed body is a closed solid"
    );
    assert_eq!(
        carved.iter_shells().count(),
        1,
        "one connected body remains"
    );
    assert_eq!(
        carved.iter_faces().count(),
        6,
        "a smaller box still has six faces"
    );
    let (lo, hi) = x_span(&carved);
    assert!(
        (lo - 0.0).abs() <= 1.0e-6 && (hi - 7.0).abs() <= 1.0e-6,
        "the cut wall lands at x=7"
    );
    let (zlo, zhi) = z_span(&carved);
    assert!((zlo - 0.0).abs() <= 1.0e-6 && (zhi - 10.0).abs() <= 1.0e-6);
    assert!(
        carved
            .iter_edges()
            .any(|edge| matches!(edge.label().role, EdgeRole::Intersection { .. })),
        "the cut wall meets the trimmed cap faces along intersection edges",
    );
}

#[test]
fn a_traversing_cut_exports_to_step() {
    let mut ids = Ids::new();
    let (base, tool) = trim_solids(&mut ids);
    let Ok(carved) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("the trim cut builds");
    };
    assert!(
        carved
            .to_step_body()
            .is_ok_and(|text| text.contains("MANIFOLD_SOLID_BREP")),
        "a trimmed body lowers to a STEP solid",
    );
}

#[test]
fn a_traversing_cut_is_deterministic() {
    let mut ids = Ids::new();
    let (base, tool) = trim_solids(&mut ids);
    let Ok(first) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("the trim cut builds");
    };
    let Ok(second) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("the trim cut builds");
    };
    assert_eq!(geometry_fingerprint(&first), geometry_fingerprint(&second));
    assert_eq!(
        edge_role_fingerprint(&first),
        edge_role_fingerprint(&second)
    );
}

#[test]
fn a_severing_cut_splits_into_two_bodies() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 10.0, 10.0);
    let tool = block(&mut ids, 3.0, -1.0, -1.0, 4.0, 12.0, 12.0);
    let Ok(carved) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("a tool through the middle severs the body into two");
    };
    assert!(carved.validate(TOL).is_ok());
    assert_eq!(
        carved.iter_shells().count(),
        2,
        "two disjoint bodies remain"
    );
    assert!(is_manifold(&carved));
    assert!(
        (mesh_volume(&carved) - 600.0).abs() <= 1.0e-4,
        "a four-wide slot leaves two three-by-ten-by-ten blocks",
    );
}

#[test]
fn a_fragmented_boolean_is_deterministic() {
    let mut ids = Ids::new();
    let base = box_solid(&mut ids, 0.0, 0.0, 0.0, 2.0, 1.0);
    let tool = box_solid(&mut ids, 0.5, 0.5, -1.0, 1.0, 3.0);
    let Ok(first) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("the through-pocket builds");
    };
    let Ok(second) = boolean(&base, &tool, BooleanOp::Difference, TOL) else {
        panic!("the through-pocket builds");
    };
    assert_eq!(
        geometry_fingerprint(&first),
        geometry_fingerprint(&second),
        "fragment ordinals and conform vertices are stable across runs",
    );
    assert_eq!(
        edge_role_fingerprint(&first),
        edge_role_fingerprint(&second)
    );
}

fn mesh_volume(solid: &BrepSolid) -> f64 {
    use bone_types::{AngleTolerance, ChordHeightTolerance};
    let Ok(mesh) = solid.tessellate(
        ChordHeightTolerance::from_mm(0.001),
        AngleTolerance::from_radians(0.05),
    ) else {
        panic!("solid tessellates");
    };
    mesh.faces()
        .iter()
        .flat_map(|slab| {
            let positions = slab.positions().to_vec();
            slab.triangles().iter().map(move |triangle| {
                let p = |index: u32| positions[index as usize].coords_mm();
                let (ax, ay, az) = p(triangle[0]);
                let (bx, by, bz) = p(triangle[1]);
                let (cx, cy, cz) = p(triangle[2]);
                let cross = (by * cz - bz * cy, bz * cx - bx * cz, bx * cy - by * cx);
                (ax * cross.0 + ay * cross.1 + az * cross.2) / 6.0
            })
        })
        .sum()
}

#[test]
fn a_coaxial_bore_hollows_a_cylinder() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let stock = cyl_solid(&mut ids, 0.0, 0.0, 0.0, 5.0, 10.0);
    let bore = cyl_solid(&mut ids, 0.0, 0.0, -1.0, 2.0, 12.0);
    let tube = match boolean(&stock, &bore, BooleanOp::Difference, TOL) {
        Ok(tube) => tube,
        Err(error) => panic!("a coaxial bore hollows the cylinder into a tube: {error:?}"),
    };
    assert!(tube.validate(TOL).is_ok(), "the bored cylinder is closed");
    assert!(is_manifold(&tube), "the bored cylinder is 2-manifold");
    let expected = PI * 5.0 * 5.0 * 10.0 - PI * 2.0 * 2.0 * 10.0;
    assert!(
        (mesh_volume(&tube) - expected).abs() <= 1.0e-1,
        "the bore removes a coaxial plug: got {}, want {expected}",
        mesh_volume(&tube),
    );
    assert!(
        tube.iter_edges()
            .any(|edge| matches!(edge.curve(), EdgeCurve3::Arc(_) | EdgeCurve3::Circle(_))),
        "the inner wall keeps arc rims",
    );
}

#[test]
fn an_offset_bore_hollows_a_cylinder() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let stock = cyl_solid(&mut ids, 0.0, 0.0, 0.0, 5.0, 10.0);
    let bore = cyl_solid(&mut ids, 2.0, 0.0, -1.0, 1.0, 12.0);
    let bored = match boolean(&stock, &bore, BooleanOp::Difference, TOL) {
        Ok(bored) => bored,
        Err(error) => panic!("an offset bore hollows the cylinder: {error:?}"),
    };
    assert!(bored.validate(TOL).is_ok(), "the bored cylinder is closed");
    assert!(is_manifold(&bored), "the bored cylinder is 2-manifold");
    let expected = PI * 5.0 * 5.0 * 10.0 - PI * 1.0 * 1.0 * 10.0;
    assert!(
        (mesh_volume(&bored) - expected).abs() <= 1.0e-1,
        "the offset bore removes a parallel plug: got {}, want {expected}",
        mesh_volume(&bored),
    );
}

#[test]
fn a_coaxial_bore_is_byte_identical_across_rebuilds() {
    let mut ids = Ids::new();
    let stock = cyl_solid(&mut ids, 0.0, 0.0, 0.0, 5.0, 10.0);
    let bore = cyl_solid(&mut ids, 0.0, 0.0, -1.0, 2.0, 12.0);
    let Ok(first) = boolean(&stock, &bore, BooleanOp::Difference, TOL) else {
        panic!("first bore");
    };
    let Ok(second) = boolean(&stock, &bore, BooleanOp::Difference, TOL) else {
        panic!("second bore");
    };
    assert_eq!(
        first.content_key().bytes(),
        second.content_key().bytes(),
        "a coaxial bore rebuilds byte-identically",
    );
}

fn y_cyl_solid(ids: &mut Ids, cx: f64, cz: f64, y0: f64, radius: f64, depth: f64) -> BrepSolid {
    let Ok(plane) = Plane3::new(
        Point3::from_mm(0.0, y0, 0.0),
        UnitVec3::z_axis(),
        UnitVec3::x_axis(),
        TOL,
    ) else {
        panic!("orthonormal axes");
    };
    let Ok(disk) = Circle2::new(Point2::from_mm(cz, cx), mm(radius), TOL) else {
        panic!("positive radius");
    };
    let circle = ProfileLoop::Closed {
        curve: Curve2Kind::Circle(disk),
        curve_entity: ids.entities.insert(()),
    };
    let profile = ExtrudeProfile::new(plane, vec![circle]);
    let extrude = ids.features.insert(());
    let Ok(solid) = evaluate_extrude(extrude, &profile, &blind(depth)) else {
        panic!("y cylinder extrude builds");
    };
    solid
}

fn bored_box(ids: &mut Ids) -> BrepSolid {
    let stock = block(ids, 0.0, 0.0, 0.0, 10.0, 10.0, 6.0);
    let bore = cyl_solid(ids, 5.0, 5.0, -1.0, 2.0, 8.0);
    match boolean(&stock, &bore, BooleanOp::Difference, TOL) {
        Ok(bored) => bored,
        Err(error) => panic!("the stock bores cleanly: {error:?}"),
    }
}

#[test]
fn a_second_cylinder_cut_into_a_bored_box_keeps_both_holes() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let bored = bored_box(&mut ids);
    let tool = cyl_solid(&mut ids, 2.0, 2.0, -1.0, 1.0, 8.0);
    let carved = match boolean(&bored, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a second bore cuts a body that already has one: {error:?}"),
    };
    assert!(
        carved.validate(TOL).is_ok(),
        "the twice-bored box is closed"
    );
    assert!(is_manifold(&carved), "the twice-bored box is 2-manifold");
    let expected = 600.0 - PI * 2.0 * 2.0 * 6.0 - PI * 1.0 * 1.0 * 6.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-1,
        "both round holes survive: got {}, want {expected}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_blind_cylinder_cut_into_a_bored_box_leaves_a_floor() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let bored = bored_box(&mut ids);
    let tool = cyl_solid(&mut ids, 2.0, 2.0, 3.0, 1.0, 5.0);
    let carved = match boolean(&bored, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a blind bore into a bored box: {error:?}"),
    };
    assert!(carved.validate(TOL).is_ok(), "the carved body is closed");
    assert!(is_manifold(&carved), "the carved body is 2-manifold");
    let expected = 600.0 - PI * 2.0 * 2.0 * 6.0 - PI * 1.0 * 1.0 * 3.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-1,
        "the blind plug stops at the floor: got {}, want {expected}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_cylinder_cut_into_the_side_of_a_bored_box() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let bored = bored_box(&mut ids);
    // axis perpendicular to the through-bore, cutting a flat side, clear of the bore
    let tool = y_cyl_solid(&mut ids, 2.0, 3.0, -1.0, 1.0, 12.0);
    let carved = match boolean(&bored, &tool, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a side cut perpendicular to the bore: {error:?}"),
    };
    assert!(carved.validate(TOL).is_ok(), "the side-cut body is closed");
    assert!(is_manifold(&carved), "the side-cut body is 2-manifold");
    let expected = 600.0 - PI * 2.0 * 2.0 * 6.0 - PI * 1.0 * 1.0 * 10.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-1,
        "the cross bore removes its own plug, keeps the first: got {}, want {expected}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_protruding_ring_boss_joins_at_the_host_face() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let ring = revolve_tube(&mut ids, 2.0, 3.0, 3.0, 8.0);
    let merged = match boolean(&base, &ring, BooleanOp::Union, TOL) {
        Ok(merged) => merged,
        Err(error) => panic!("a protruding ring boss merges into its host: {error:?}"),
    };
    assert!(merged.validate(TOL).is_ok(), "the merged body is closed");
    assert!(is_manifold(&merged), "the merged body is 2-manifold");
    let expected = 500.0 + PI * (3.0 * 3.0 - 2.0 * 2.0) * 3.0;
    assert!(
        (mesh_volume(&merged) - expected).abs() <= 1.0e-1,
        "the stub above the host adds its ring volume: got {}, want {expected}",
        mesh_volume(&merged),
    );
}

#[test]
fn a_through_ring_boss_joins_both_host_faces() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let ring = revolve_tube(&mut ids, 2.0, 3.0, -2.0, 7.0);
    let merged = match boolean(&base, &ring, BooleanOp::Union, TOL) {
        Ok(merged) => merged,
        Err(error) => panic!("a through ring boss merges through its host: {error:?}"),
    };
    assert!(merged.validate(TOL).is_ok(), "the merged body is closed");
    assert!(is_manifold(&merged), "the merged body is 2-manifold");
    let band = PI * (3.0 * 3.0 - 2.0 * 2.0);
    let expected = 500.0 + band * 2.0 + band * 2.0;
    assert!(
        (mesh_volume(&merged) - expected).abs() <= 1.0e-1,
        "both protruding stubs add their ring volume: got {}, want {expected}",
        mesh_volume(&merged),
    );
}

#[test]
fn a_blind_annular_cut_leaves_a_washer_void() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let ring = revolve_tube(&mut ids, 2.0, 3.0, 2.0, 8.0);
    let carved = match boolean(&base, &ring, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a blind annular cut carves a washer groove: {error:?}"),
    };
    assert!(carved.validate(TOL).is_ok(), "the carved body is closed");
    assert!(is_manifold(&carved), "the carved body is 2-manifold");
    let expected = 500.0 - PI * (3.0 * 3.0 - 2.0 * 2.0) * 3.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-1,
        "the groove stops at its floor, keeping the central plug: got {}, want {expected}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_through_annular_cut_severs_a_ring_channel() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let ring = revolve_tube(&mut ids, 2.0, 3.0, -1.0, 6.0);
    let carved = match boolean(&base, &ring, BooleanOp::Difference, TOL) {
        Ok(carved) => carved,
        Err(error) => panic!("a through annular cut carves a ring channel: {error:?}"),
    };
    assert!(carved.validate(TOL).is_ok(), "the carved body is closed");
    assert!(is_manifold(&carved), "the carved body is 2-manifold");
    let expected = 500.0 - PI * (3.0 * 3.0 - 2.0 * 2.0) * 5.0;
    assert!(
        (mesh_volume(&carved) - expected).abs() <= 1.0e-1,
        "the channel pierces the whole height: got {}, want {expected}",
        mesh_volume(&carved),
    );
}

#[test]
fn a_flip_side_annular_cut_keeps_the_ring_the_tool_overlaps() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let ring = revolve_tube(&mut ids, 2.0, 3.0, -1.0, 6.0);
    let kept = match boolean(&base, &ring, BooleanOp::Intersection, TOL) {
        Ok(kept) => kept,
        Err(error) => panic!("flip-side cut keeps the base-tool overlap: {error:?}"),
    };
    assert!(kept.validate(TOL).is_ok(), "the overlap ring is closed");
    assert!(is_manifold(&kept), "the overlap ring is 2-manifold");
    let expected = PI * (3.0 * 3.0 - 2.0 * 2.0) * 5.0;
    assert!(
        (mesh_volume(&kept) - expected).abs() <= 1.0e-1,
        "flip-side keeps only the ring the base and tool share: got {}, want {expected}",
        mesh_volume(&kept),
    );
}

#[test]
fn a_blind_flip_side_annular_cut_keeps_the_overlap_ring() {
    use core::f64::consts::PI;
    let mut ids = Ids::new();
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let ring = revolve_tube(&mut ids, 2.0, 3.0, 2.0, 8.0);
    let kept = match boolean(&base, &ring, BooleanOp::Intersection, TOL) {
        Ok(kept) => kept,
        Err(error) => panic!("a blind flip-side cut keeps the overlap: {error:?}"),
    };
    assert!(kept.validate(TOL).is_ok(), "the overlap ring is closed");
    assert!(is_manifold(&kept), "the overlap ring is 2-manifold");
    let expected = PI * (3.0 * 3.0 - 2.0 * 2.0) * 3.0;
    assert!(
        (mesh_volume(&kept) - expected).abs() <= 1.0e-1,
        "the overlap spans only where base and tool meet: got {}, want {expected}",
        mesh_volume(&kept),
    );
}

#[test]
fn an_annular_merge_and_cut_are_byte_identical_across_rebuilds() {
    let mut ids = Ids::new();
    let base = block(&mut ids, -5.0, -5.0, 0.0, 10.0, 10.0, 5.0);
    let ring = revolve_tube(&mut ids, 2.0, 3.0, 2.0, 8.0);
    let key = |op: BooleanOp| match boolean(&base, &ring, op, TOL) {
        Ok(solid) => solid.content_key().bytes(),
        Err(error) => panic!("an annular {op:?} builds: {error:?}"),
    };
    assert_eq!(
        key(BooleanOp::Union),
        key(BooleanOp::Union),
        "an annular merge rebuilds byte-identically",
    );
    assert_eq!(
        key(BooleanOp::Difference),
        key(BooleanOp::Difference),
        "an annular cut rebuilds byte-identically",
    );
}

#[test]
fn a_recut_bored_box_is_byte_identical_across_rebuilds() {
    let mut ids = Ids::new();
    let bored = bored_box(&mut ids);
    let tool = cyl_solid(&mut ids, 2.0, 2.0, -1.0, 1.0, 8.0);
    let Ok(first) = boolean(&bored, &tool, BooleanOp::Difference, TOL) else {
        panic!("first recut");
    };
    let Ok(second) = boolean(&bored, &tool, BooleanOp::Difference, TOL) else {
        panic!("second recut");
    };
    assert_eq!(
        first.content_key().bytes(),
        second.content_key().bytes(),
        "re-cutting a bored box rebuilds byte-identically",
    );
}
