import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:service_api/service_api.dart'; class GameResultArgs { final String gameType; final String contextId; final int primaryScore; // [Legacy Support] 기존 게임 호환용 필드 final String? userId; final String? userName; // [Fix] userName 필드 존재 확인 final int? secondaryScore; // [Fix] 타입 불일치 해결: String을 받는 비동기 함수로 명시 final Future Function(String)? onProgressSave; final VoidCallback? onNextGame; // [New Feature] 신규 게임 자동 저장용 필드 final int? stars; final int? levelIndex; final String Function(int score, int? subScore)? scoreFormatter; GameResultArgs({ required this.gameType, required this.contextId, required this.primaryScore, this.userId, this.userName, this.secondaryScore, this.onProgressSave, this.onNextGame, this.stars, this.levelIndex, this.scoreFormatter, }); } abstract class BaseGameScreen extends StatefulWidget { final VoidCallback? onNextGame; const BaseGameScreen({super.key, this.onNextGame}); } abstract class BaseGameScreenState extends State { void showCommonGameCompletion(GameResultArgs args) async { // 1. [New] 자동 저장 로직 if (args.stars != null && args.levelIndex != null) { try { if (!mounted) return; final identityService = context.read(); await identityService.submitGameResult( gameType: args.gameType, level: args.levelIndex!, stars: args.stars!, ); } catch (e) { debugPrint("자동 저장 실패: $e"); } } // 2. [Legacy] 수동 저장 로직 호환 (기존 게임용) if (args.onProgressSave != null) { // 기존 게임들이 String 인자를 기대하므로 더미 문자열 전달 await args.onProgressSave!("legacy_save"); } if (!mounted) return; // 3. 팝업 표시 final VoidCallback? nextCallback = widget.onNextGame ?? args.onNextGame; final bool isDailyCourse = nextCallback != null; showDialog( context: context, barrierDismissible: false, builder: (ctx) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: const Row( children: [ Icon(Icons.emoji_events, color: Colors.orange, size: 28), SizedBox(width: 8), Text('훈련 완료!'), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( args.scoreFormatter != null ? args.scoreFormatter!(args.primaryScore, args.secondaryScore) : "점수: ${args.primaryScore}", style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), if (args.stars != null) Row( children: List.generate(3, (index) => Icon( index < args.stars! ? Icons.star : Icons.star_border, color: Colors.amber, size: 32, )), ), if (args.stars != null) const SizedBox(height: 16), Text(isDailyCourse ? "수고하셨습니다. 다음 훈련으로 이동합니다." : "수고하셨습니다. 로비로 돌아갑니다." ), ], ), actions: [ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.blueAccent, foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), onPressed: () { Navigator.pop(ctx); if (isDailyCourse) { nextCallback!(); } else { if (Navigator.canPop(context)) { Navigator.pop(context); } } }, child: Text(isDailyCourse ? "다음 게임" : "확인"), ), ], ), ); } }