# encoding: UTF-8
begin
  puts "###DZW-STEP1A-BASEPLATE-20260920"
  m = Sketchup.active_model
  bk = 'E:/도진팩토리/3D스캔및티칭시스템/_자동화/autosave/BACKUP_before_step1a.skp'
  m.save_copy(bk)
  puts "BACKUP=#{bk}"
  cov = nil
  m.active_entities.each do |e|
    next unless e.is_a?(Sketchup::Group) || e.is_a?(Sketchup::ComponentInstance)
    cov = e if (e.respond_to?(:name) ? e.name.to_s : '') == '하부프레임커버'
  end
  k = nil
  if cov
    (cov.entities.grep(Sketchup::Group) + cov.entities.grep(Sketchup::ComponentInstance)).each do |q|
      nm = (q.respond_to?(:name) ? q.name.to_s : '')
      k = q if nm == '조립부원판_20260919'
    end
  end
  if k.nil?
    puts "STOP: 조립부원판 미발견"
  else
    t = k.transformation
    sx = t.xscale
    sy = t.yscale
    sz = t.zscale
    puts "1) 스케일 굽기: scale=[#{sx.round(5)},#{sy.round(5)},#{sz.round(5)}]"
    wt0 = cov.transformation * t
    p0 = []
    k.entities.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| p0 << v.position.transform(wt0) } }
    b0 = [p0.map { |p| p.x.to_mm }.minmax, p0.map { |p| p.y.to_mm }.minmax, p0.map { |p| p.z.to_mm }.minmax]
    puts "   굽기 전 월드 X=#{b0[0].map { |v| v.round(2) }.inspect} Y=#{b0[1].map { |v| v.round(2) }.inspect} Z=#{b0[2].map { |v| v.round(2) }.inspect}"
    sc = Geom::Transformation.scaling(sx, sy, sz)
    vs = []
    k.entities.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| vs << v } }
    vs.uniq!
    mv = []
    vc = []
    maxd = 0.0
    vs.each do |v|
      np = v.position.transform(sc)
      d = (np - v.position)
      maxd = d.length.to_mm if d.length.to_mm > maxd
      mv << v
      vc << d
    end
    puts "   로컬 정점 이동 최대 #{maxd.round(1)}mm (로컬계, 스케일 제거분)"
    m.start_operation('하판 스케일 정규화 + 홀 정원 복구', true)
    k.entities.transform_by_vectors(mv, vc)
    k.transformation = t * sc.inverse
    # 검산: 월드 형상 불변?
    wt1 = cov.transformation * k.transformation
    p1 = []
    k.entities.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| p1 << v.position.transform(wt1) } }
    b1 = [p1.map { |p| p.x.to_mm }.minmax, p1.map { |p| p.y.to_mm }.minmax, p1.map { |p| p.z.to_mm }.minmax]
    puts "   굽기 후 월드 X=#{b1[0].map { |v| v.round(2) }.inspect} Y=#{b1[1].map { |v| v.round(2) }.inspect} Z=#{b1[2].map { |v| v.round(2) }.inspect}"
    puts "   scale 확인=[#{k.transformation.xscale.round(5)},#{k.transformation.yscale.round(5)},#{k.transformation.zscale.round(5)}]"
    # 2) 홀 정원 복구 (로컬계에서 XY 원형화, 반지름 9.0mm)
    r = 9.0
    loops = []
    k.entities.grep(Sketchup::Face).each do |fa|
      fa.loops.each do |lp|
        next if lp.outer?
        next if lp.vertices.length < 8
        loops << lp
      end
    end
    fixed = 0
    mv2 = []
    vc2 = []
    maxh = 0.0
    seen = {}
    loops.each do |lp|
      pv = lp.vertices
      cx = pv.map { |v| v.position.x.to_f }.inject(:+) / pv.length
      cy = pv.map { |v| v.position.y.to_f }.inject(:+) / pv.length
      ok = true
      pv.each do |v|
        next if seen[v.object_id]
        dx = v.position.x.to_f - cx
        dy = v.position.y.to_f - cy
        len = Math.sqrt(dx * dx + dy * dy)
        next if len < 1.0e-9
        nx = cx + dx / len * r.mm
        ny = cy + dy / len * r.mm
        np = Geom::Point3d.new(nx, ny, v.position.z)
        d = np - v.position
        dm = d.length.to_mm
        ok = false if dm > 25.0
        maxh = dm if dm > maxh
        seen[v.object_id] = true
        mv2 << v
        vc2 << d
      end
      fixed += 1 if ok
    end
    if maxh > 25.0
      puts "   STOP: 홀 보정 이동량 #{maxh.round(1)}mm 과다 -> 홀 보정 생략"
    elsif !mv2.empty?
      k.entities.transform_by_vectors(mv2, vc2)
      puts "2) 홀 정원 복구: 내부루프 #{loops.length}개, 정점 #{mv2.length}개, 최대 이동 #{maxh.round(2)}mm, 반지름 #{r}mm"
    else
      puts "2) 홀 보정 대상 없음"
    end
    m.commit_operation
    # 검증
    rep = []
    k.entities.grep(Sketchup::Face).each do |fa|
      fa.loops.each do |lp|
        next if lp.outer?
        next if lp.vertices.length < 8
        ps = lp.vertices.map { |v| v.position.transform(cov.transformation * k.transformation) }
        bb = Geom::BoundingBox.new
        ps.each { |p| bb.add(p) }
        d = [bb.width.to_mm, bb.height.to_mm, bb.depth.to_mm].sort
        rep << [d[1].round(2), d[2].round(2)]
      end
    end
    g2 = {}
    rep.each { |a| g2[a] = (g2[a] || 0) + 1 }
    puts "3) 검증 홀 치수(월드): #{g2.to_a.sort_by { |a, c| -c }.first(4).map { |a, c| "#{a[0]}x#{a[1]} x#{c}개" }.join(' , ')}"
    pz = []
    k.entities.grep(Sketchup::Edge).each { |ed| ed.vertices.each { |v| pz << v.position.transform(cov.transformation * k.transformation) } }
    zr = pz.map { |p| p.z.to_mm }.minmax
    xr = pz.map { |p| p.x.to_mm }.minmax
    puts "   하판 월드 X=#{xr.map { |v| v.round(1) }.inspect} Z=#{zr.map { |v| v.round(1) }.inspect} 현재 기울기=#{(Math.atan((zr[1] - zr[0] - 12.0) / (xr[1] - xr[0])) * 180.0 / Math::PI).round(4)}deg (목표 6.4452, 별도 단계에서 처리)"
    ok = m.save
    puts "SAVE=#{ok.inspect} modified?=#{m.modified?.inspect}"
    puts "DONE"
  end
rescue Exception => e
  puts "EXC #{e.class}: #{e.message}"
  puts e.backtrace.first(6).join(" | ")
end
nil
