@@ -161,11 +161,41 @@ def destroy
161161 end
162162
163163 def sync
164- # Sync functionality not yet implemented
164+ return render_error_no_puuid unless @target . riot_puuid . present?
165+
166+ # Try to find an existing player (active or soft-deleted) with this PUUID
167+ player = find_player_by_puuid ( @target . riot_puuid )
168+
169+ if player
170+ # Player exists - sync from their data
171+ sync_result = sync_from_existing_player ( player )
172+ else
173+ # Player doesn't exist - sync from Riot API
174+ sync_result = sync_from_riot_api
175+ end
176+
177+ if sync_result [ :success ]
178+ watchlist = @target . scouting_watchlists . find_by ( organization : current_organization )
179+ render_success ( {
180+ scouting_target : JSON . parse (
181+ ScoutingTargetSerializer . render ( @target . reload , watchlist : watchlist )
182+ ) ,
183+ message : sync_result [ :message ]
184+ } )
185+ else
186+ render_error (
187+ message : sync_result [ :error ] ,
188+ code : sync_result [ :code ] || 'SYNC_ERROR' ,
189+ status : :unprocessable_entity
190+ )
191+ end
192+ rescue StandardError => e
193+ Rails . logger . error ( "Scouting sync error: #{ e . message } " )
194+ Rails . logger . error ( e . backtrace . join ( "\n " ) )
165195 render_error (
166- message : 'Sync functionality not yet implemented' ,
167- code : 'NOT_IMPLEMENTED ' ,
168- status : :not_implemented
196+ message : "Failed to sync scouting target: #{ e . message } " ,
197+ code : 'SYNC_ERROR ' ,
198+ status : :internal_server_error
169199 )
170200 end
171201
@@ -310,6 +340,84 @@ def target_params
310340 champion_pool : [ ]
311341 )
312342 end
343+
344+ # Find player by PUUID (including soft-deleted)
345+ def find_player_by_puuid ( puuid )
346+ Player . with_deleted . find_by ( riot_puuid : puuid )
347+ end
348+
349+ # Sync from existing player in database
350+ def sync_from_existing_player ( player )
351+ # Use RosterManagementService to calculate stats
352+ service = Players ::RosterManagementService . new (
353+ player : player ,
354+ organization : player . organization ,
355+ current_user : current_user
356+ )
357+
358+ # Check if player has enough matches
359+ current_match_count = player . player_match_stats . count
360+ if current_match_count < 50
361+ # Try to sync more matches from Riot
362+ begin
363+ sync_service = Players ::Services ::RiotSyncService . new ( player . organization , player . region )
364+ imported = service . send ( :sync_player_matches_comprehensive , sync_service , 50 )
365+ Rails . logger . info ( "Imported #{ imported } additional matches during scouting sync" )
366+ rescue StandardError => e
367+ Rails . logger . warn ( "Failed to import additional matches: #{ e . message } " )
368+ end
369+ end
370+
371+ # Calculate comprehensive stats
372+ recent_perf = service . send ( :calculate_recent_performance , player , limit : 50 )
373+ champion_stats = service . send ( :calculate_champion_stats , player , limit : 50 )
374+ trend = service . send ( :calculate_performance_trend , player , limit : 50 )
375+ recent_perf [ :champion_pool_stats ] = champion_stats
376+
377+ # Update scouting target
378+ @target . update! (
379+ summoner_name : player . summoner_name ,
380+ region : service . send ( :normalize_region , player . region ) ,
381+ role : player . role ,
382+ current_tier : player . solo_queue_tier ,
383+ current_rank : player . solo_queue_rank ,
384+ current_lp : player . solo_queue_lp ,
385+ champion_pool : service . send ( :calculate_champion_pool_from_stats , player ) ,
386+ recent_performance : recent_perf ,
387+ performance_trend : trend ,
388+ real_name : player . real_name ,
389+ avatar_url : player . avatar_url ,
390+ twitter_handle : player . twitter_handle
391+ )
392+
393+ {
394+ success : true ,
395+ message : "Synced from player database (#{ player . player_match_stats . count } matches analyzed)"
396+ }
397+ rescue StandardError => e
398+ Rails . logger . error ( "Error syncing from player: #{ e . message } " )
399+ { success : false , error : e . message , code : 'PLAYER_SYNC_ERROR' }
400+ end
401+
402+ # Sync from Riot API (when player doesn't exist in database)
403+ def sync_from_riot_api
404+ # This would require creating a temporary player or using Riot API directly
405+ # For now, return not implemented for this case
406+ {
407+ success : false ,
408+ error : 'Player not found in database. Add to roster first to enable sync.' ,
409+ code : 'PLAYER_NOT_IN_DATABASE'
410+ }
411+ end
412+
413+ # Error response when PUUID is missing
414+ def render_error_no_puuid
415+ render_error (
416+ message : 'Cannot sync: Riot PUUID is required' ,
417+ code : 'PUUID_REQUIRED' ,
418+ status : :unprocessable_entity
419+ )
420+ end
313421 end
314422 end
315423 end
0 commit comments