require 'xcodeproj'

# Adds RealtimeKit screenshare Swift sources to a Broadcast Upload Extension target.
# Also contains require-time shims that patch xcodeproj for Xcode 26 compatibility —
# they must run before CocoaPods opens any project, which is why they live here rather
# than inside the post_install hook.
#
# Usage in Podfile:
#
#   require Pod::Executable.execute_command('node', ['-p',
#     'require.resolve(
#       "@cloudflare/realtimekit-react-native/ios/scripts/screenshare_sources.rb",
#       {paths: [process.argv[1]]},
#     )', __dir__]).strip
#
#   post_install do |installer|
#     add_screenshare_sources(
#       installer,
#       project_name: 'YourApp',
#       extension_target_name: 'YourAppScreenshare'
#     )
#   end

# --- Xcode 26 shim: shellScript stored as Array instead of String ---------------
# xcodeproj ≤1.27 expects shellScript to be a String; Xcode 26 writes an Array.
# Scoped to PBXShellScriptBuildPhase#shell_script= to avoid silencing type errors
# on unrelated attributes in other classes.
if defined?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) &&
   !Xcodeproj::Project::Object::PBXShellScriptBuildPhase
       .instance_variable_defined?(:@_rtk_xcode26_shim)
  Xcodeproj::Project::Object::PBXShellScriptBuildPhase
    .instance_variable_set(:@_rtk_xcode26_shim, true)
  Xcodeproj::Project::Object::PBXShellScriptBuildPhase.prepend(Module.new do
    def shell_script=(value)
      value = value.join("\n") if value.is_a?(Array)
      super
    end
  end)
end

# --- Xcode 26 shim: objectVersion 90 unknown to xcodeproj ≤1.27 ----------------
# CocoaPods mirrors the user project's objectVersion into Pods.xcodeproj via
# Project.new(path, false, 90), which raises because COMPATIBILITY_VERSION_BY_OBJECT_VERSION
# only covers up to version 77. Register 90 and bump LAST_KNOWN_OBJECT_VERSION to silence
# the "version higher than supported" warning from initialize_from_file.
if defined?(Xcodeproj::Constants::COMPATIBILITY_VERSION_BY_OBJECT_VERSION) &&
   !Xcodeproj::Constants.instance_variable_defined?(:@_rtk_xcode26_version_shim)
  Xcodeproj::Constants.instance_variable_set(:@_rtk_xcode26_version_shim, true)

  unless Xcodeproj::Constants::COMPATIBILITY_VERSION_BY_OBJECT_VERSION.key?(90)
    new_compat = Xcodeproj::Constants::COMPATIBILITY_VERSION_BY_OBJECT_VERSION.merge(90 => 'Xcode 26.0')
    Xcodeproj::Constants.send(:remove_const, :COMPATIBILITY_VERSION_BY_OBJECT_VERSION)
    Xcodeproj::Constants.const_set(:COMPATIBILITY_VERSION_BY_OBJECT_VERSION, new_compat.freeze)
  end

  if Xcodeproj::Constants::LAST_KNOWN_OBJECT_VERSION < 90
    Xcodeproj::Constants.send(:remove_const, :LAST_KNOWN_OBJECT_VERSION)
    Xcodeproj::Constants.const_set(:LAST_KNOWN_OBJECT_VERSION, 90)
  end
end

# @param installer               CocoaPods installer object (from post_install)
# @param project_name:           Xcode project name without .xcodeproj extension
# @param extension_target_name:  Name of the Broadcast Upload Extension target
# @param screenshare_source_path: Override path to screenshare Swift files (default: ios/screenshare/)
# @param group_name:             Navigator group name to create (default: RTKScreenshareCore)
def add_screenshare_sources(
  installer,
  project_name:,
  extension_target_name:,
  screenshare_source_path: nil,
  group_name: 'RTKScreenshareCore'
)
  # Default source path: ios/screenshare/ inside this package
  screenshare_src = screenshare_source_path || File.expand_path('../screenshare', __dir__)

  main_proj_path = File.join(File.dirname(installer.sandbox.root), "#{project_name}.xcodeproj")

  unless File.exist?(main_proj_path)
    Pod::UI.warn "add_screenshare_sources: '#{main_proj_path}' not found — skipping."
    return
  end

  main_proj  = Xcodeproj::Project.open(main_proj_path)
  ext_target = main_proj.targets.find { |t| t.name == extension_target_name }

  unless ext_target
    Pod::UI.warn "add_screenshare_sources: target '#{extension_target_name}' not found in #{project_name}.xcodeproj — skipping."
    return
  end

  # Xcode 16+ may use PBXFileSystemSynchronizedRootGroup for the extension folder.
  # That type does not support find_subpath/new_group, so fall back to a sibling classic group.
  sync_group_class = defined?(Xcodeproj::Project::Object::PBXFileSystemSynchronizedRootGroup) &&
                     Xcodeproj::Project::Object::PBXFileSystemSynchronizedRootGroup

  found = main_proj.main_group.find_subpath(extension_target_name, false)
  parent_group = if found.nil?
    main_proj.main_group.new_group(extension_target_name, extension_target_name)
  elsif sync_group_class && found.is_a?(sync_group_class)
    # Find an existing classic PBXGroup sibling, or create one
    main_proj.main_group.children.find do |child|
      child.is_a?(Xcodeproj::Project::Object::PBXGroup) &&
        !(sync_group_class && child.is_a?(sync_group_class)) &&
        (child.name == extension_target_name || child.path == extension_target_name)
    end || main_proj.main_group.new_group(extension_target_name, extension_target_name)
  else
    found
  end

  rtk_group = parent_group.find_subpath(group_name, false) ||
              parent_group.new_group(group_name, screenshare_src)

  Dir.glob(File.join(screenshare_src, '*.swift')).each do |swift_file|
    basename = File.basename(swift_file)
    # Skip files already present in the build phase
    next if ext_target.source_build_phase.files.any? do |bf|
      bf.file_ref&.name == basename || bf.file_ref&.path&.end_with?(basename)
    end

    file_ref = rtk_group.new_reference(swift_file)
    ext_target.source_build_phase.add_file_reference(file_ref)
  end

  # --- Xcode 26 fix: restore Embed Foundation Extensions destination -------------
  # Xcode 26 (objectVersion 90) writes the embed phase destination using a new
  # string-typed key `dstSubfolder` instead of the classic integer `dstSubfolderSpec`.
  # xcodeproj ≤1.27 doesn't know `dstSubfolder`, so it drops it on read and, since
  # `dst_subfolder_spec` reads as nil, omits it entirely on save. The embed phase then
  # has no destination and Xcode never copies the .appex into the app's PlugIns/ folder.
  # Re-assert dst_subfolder_spec = 13 (:plug_ins) on any host target's copy-files phase
  # that embeds the extension, so every `pod install` self-heals the destination.
  plugins_spec = Xcodeproj::Constants::COPY_FILES_BUILD_PHASE_DESTINATIONS[:plug_ins]
  main_proj.targets.each do |target|
    next if target.name == extension_target_name

    target.build_phases.each do |phase|
      next unless phase.is_a?(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase)
      next unless phase.files.any? { |f| f.file_ref&.path&.end_with?('.appex') }

      phase.dst_subfolder_spec = plugins_spec
    end
  end

  main_proj.save
end
