import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:descope/descope.dart'; import '../../../core/services/auth_proxy_service.dart'; class QRScanScreen extends StatefulWidget { const QRScanScreen({super.key}); @override State createState() => _QRScanScreenState(); } class _QRScanScreenState extends State { final _log = Logger('QRScanScreen'); final MobileScannerController controller = MobileScannerController( detectionSpeed: DetectionSpeed.noDuplicates, ); bool _isScanned = false; @override void dispose() { controller.dispose(); super.dispose(); } Future _onDetect(BarcodeCapture capture) async { if (_isScanned) return; final List barcodes = capture.barcodes; for (final barcode in barcodes) { if (barcode.rawValue != null) { _isScanned = true; String qrData = barcode.rawValue!; String pendingRef = qrData; // URL 형식이라면 'ref' 파라미터 추출 시도 if (qrData.startsWith('http')) { try { final uri = Uri.parse(qrData); if (uri.queryParameters.containsKey('ref')) { pendingRef = uri.queryParameters['ref']!; } } catch (e) { _log.warning('Failed to parse QR URL: $qrData', e); } } _log.info('QR Code detected raw: $qrData, ref: $pendingRef'); final sessionToken = Descope.sessionManager.session?.sessionToken.jwt; if (sessionToken == null) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('로그인이 필요합니다.'), backgroundColor: Colors.red), ); context.pop(); } return; } try { // Call backend API to approve login with clean ref await AuthProxyService.approveQrLogin(pendingRef, sessionToken); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('로그인 승인 완료!'), backgroundColor: Colors.green, ), ); // Wait a bit and go back await Future.delayed(const Duration(milliseconds: 500)); if (mounted) context.pop(); } } catch (e) { _log.severe("QR Approval Failed", e); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('승인 실패: $e'), backgroundColor: Colors.red), ); // Allow rescanning after a delay await Future.delayed(const Duration(seconds: 2)); _isScanned = false; } } break; } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Scan QR Code'), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => context.pop(), ), ), body: MobileScanner( controller: controller, onDetect: _onDetect, errorBuilder: (context, error, child) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error, color: Colors.red, size: 50), const SizedBox(height: 10), Text('Camera Error: ${error.errorCode}'), ], ), ); }, ), ); } }