"""Place surveyed filter reference wires after separately checked rigid registration."""
import argparse
import json
from pathlib import Path

import cadquery as cq
from build_filter_rim_survey import build_reference
from filter_rim_survey import analyze
from intake_survey import dot, length, subtract
from register_round_cover import mapped, registration


def map_reference(survey, transform):
    if (survey.get('status')!='within_entered_comparison_limit' or
            transform.get('status')!='within_entered_comparison_limit' or
            survey.get('frame')!=transform.get('source_frame')):
        raise ValueError('Reference placement requires passing survey and registration comparisons in the same source frame/configuration.')
    rotation=transform['rotation_source_to_target'];translation=transform['translation_source_to_target_mm']
    center=mapped(survey['derived_rim_center_xyz_mm'],rotation,translation)
    end=mapped(survey['derived_closed_end_plane_axis_intersection_xyz_mm'],rotation,translation)
    vector=[dot(row,survey['derived_axis_toward_closed_end_unit_vector']) for row in rotation]
    return {
        'status':'within_entered_comparison_limit','frame_name':transform['target_frame_name'],
        'derived_rim_center_xyz_mm':center,'derived_rim_radius_mm':survey['derived_rim_radius_mm'],
        'derived_axis_toward_closed_end_unit_vector':[v/length(vector) for v in vector],
        'derived_rim_to_closed_end_distance_mm':length(subtract(end,center)),
        'derived_closed_end_plane_axis_intersection_xyz_mm':end,
        'reference_only':True,
    }


def make_report(survey_path, registration_path, target_model, survey_limit, registration_limit):
    survey=analyze(survey_path,survey_limit)
    transform=registration(registration_path,target_model,survey['frame'],registration_limit)
    # Preserve opaque evidence as valid JSON before producing any artifact.
    json.dumps(transform,allow_nan=False)
    passed=all(r['status']=='within_entered_comparison_limit' for r in (survey,transform))
    report={
        'schema':'midget-filter-rim-axis-registration-report-v1','units':'mm',
        'status':'within_both_entered_comparison_limits' if passed else 'outside_entered_comparison_limits',
        'source_survey':survey,'registration':transform,
        'limits':'Survey reference placement only. Source and target coordinates remain separately recorded. The model fingerprint identifies the exact target file, not the truth of manually supplied target datums. Target geometry may be provisional. No fitted identity, sealing plane, material solid, contact, clearance or removal path is established. Engine assets are not changed.',
    }
    if passed:report['target_reference_geometry']=map_reference(survey,transform)
    return report


def main():
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--survey',type=Path,required=True)
    parser.add_argument('--registration',type=Path,required=True)
    parser.add_argument('--target-model',type=Path,required=True)
    parser.add_argument('--output-dir',type=Path,required=True)
    parser.add_argument('--survey-comparison-limit-mm',type=float,required=True)
    parser.add_argument('--registration-comparison-limit-mm',type=float,required=True)
    args=parser.parse_args()
    if args.output_dir.exists() and any(args.output_dir.iterdir()):
        parser.error('Choose an empty output directory to preserve earlier reports and reference geometry.')
    report=make_report(args.survey,args.registration,args.target_model,args.survey_comparison_limit_mm,args.registration_comparison_limit_mm)
    serialized=json.dumps(report,indent=2,allow_nan=False)+'\n'
    args.output_dir.mkdir(parents=True,exist_ok=True)
    (args.output_dir/'filter-rim-axis-registration-report.json').write_text(serialized)
    if report['status']!='within_both_entered_comparison_limits':
        print('Wrote comparison report only. No target-frame reference STEP exported.')
        raise SystemExit(1)
    cq.exporters.export(build_reference(report['target_reference_geometry']),str(args.output_dir/'filter-rim-axis-cad-reference.step'))
    print('Wrote registered reference circle/axis and both source reports. No engine part, solid or verified clearance.')


if __name__=='__main__':
    main()
