# Python Script, API Version = V23
import json, os

def match_faces_to_points(faces, points):
    matched_indices = []
    for face in faces:
        min_dist = float('inf')
        best_idx = -1
        for idx, point in enumerate(points):
            current_min = float('inf')
            for face_point in face:
                dx = face_point[0]*1000. - point[0]
                dy = face_point[1]*1000. - point[1]
                dz = face_point[2]*1000. - point[2]
                distance = (dx**2 + dy**2 + dz**2) ** 0.5
                if distance < current_min:
                    current_min = distance
            if current_min < min_dist:
                min_dist = current_min
                best_idx = idx
        matched_indices.append(best_idx)
    return matched_indices

if __name__ == "__main__":
    stp_dir = r"stp_dir\\"
    cut_info_dir = r"cut_info_dir\\"
    centerlines_dir = r"centerlines_dir\\"
    scdoc_dir = r"scdoc_dir\\"

    listdir = os.listdir(stp_dir)
    listdir.sort()

    startnum = 0
    for file_num in range(startnum, min(startnum + 3, len(listdir))):
        DocumentOpen.Execute(stp_dir + listdir[file_num])
        # EndBlock

        Body1 = BodySelection.SelectAll()
        primarySelection = FaceSelection.Create(*list(Body1.ConvertToFaces().Faces))
        secondarySelection = Selection.Empty()
        result = NamedSelection.Create(primarySelection, secondarySelection)
        # EndBlock

        result = NamedSelection.Rename("group1", "wall")
        # EndBlock

        options = FixMissingFacesOptions()
        result = FixMissingFaces.FindAndFix(options)
        # EndBlock

        Body1 = BodySelection.SelectAll()
        primarySelection = Body1
        secondarySelection = Selection.Empty()
        result = NamedSelection.Create(primarySelection, secondarySelection)
        # EndBlock

        result = NamedSelection.Rename("group1", "fluid")
        # EndBlock

        fluid = Selection.CreateByGroups(SelectionType.Primary, "fluid")
        wall = Selection.CreateByGroups(SelectionType.Primary, "wall")

        fluidfaces = list(fluid.ConvertToFaces().Faces)
        wallfaces = list(wall.ConvertToFaces().Faces)

        in_out_faces = [f for f in fluidfaces if f not in wallfaces]

        faces_points = []
        for f in in_out_faces:
            edges = list(f.Edges)
            points = []
            for edge in edges:
                p = edge.Shape.EndPoint
                points.append([p.X, p.Y, p.Z])
            faces_points.append(points)

        cut_info_path = cut_info_dir + listdir[file_num][:-4] + ".json"
        with open(cut_info_path, 'r') as f:
            cut_info_json = json.load(f)
        control_points = cut_info_json
        in_out_points = []
        in_points_ids = []
        for i, p in enumerate(control_points):
            in_out_points.append([p['plane_origin'][0], p['plane_origin'][1], p['plane_origin'][2]])
            if p["in_out"] == "in": in_points_ids.append(i)

        matched_ids = match_faces_to_points(faces_points, in_out_points)

        in_faces = [in_out_faces[i] for i in range(len(in_out_faces)) if matched_ids[i] in in_points_ids]
        out_faces = [in_out_faces[i] for i in range(len(in_out_faces)) if matched_ids[i] not in in_points_ids]

        primarySelection = FaceSelection.Create(*in_faces)
        secondarySelection = Selection.Empty()
        result = NamedSelection.Create(primarySelection, secondarySelection)
        result = NamedSelection.Rename("group1", "inlet")

        primarySelection = FaceSelection.Create(*out_faces)
        secondarySelection = Selection.Empty()
        result = NamedSelection.Create(primarySelection, secondarySelection)
        result = NamedSelection.Rename("group1", "outlet")

        DocumentSave.Execute(scdoc_dir + listdir[file_num][:-4] + ".scdoc")
        CloseWindow()
        