import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:go_router/go_router.dart'; import '../../../core/services/auth_proxy_service.dart'; class ResetPasswordScreen extends StatefulWidget { final String? loginId; // Now receiving loginId const ResetPasswordScreen({super.key, this.loginId}); @override State createState() => _ResetPasswordScreenState(); } class _ResetPasswordScreenState extends State { final TextEditingController _passwordController = TextEditingController(); final TextEditingController _confirmPasswordController = TextEditingController(); final _formKey = GlobalKey(); bool _isLoading = false; String? _loginId; bool _isPasswordObscured = true; bool _isConfirmPasswordObscured = true; @override void initState() { super.initState(); // 1. Get loginId from GoRouter state if available _loginId = widget.loginId; // 2. Fallback to URI query parameter if not available via router if (_loginId == null || _loginId!.isEmpty) { final uri = Uri.base; _loginId = uri.queryParameters['loginId']; } } Future _handlePasswordReset() async { if (_formKey.currentState?.validate() != true) return; if (_loginId == null || _loginId!.isEmpty) { _showError("유효하지 않은 재설정 링크입니다. (loginId 누락)"); return; } setState(() => _isLoading = true); try { await AuthProxyService.completePasswordReset( _loginId!, _passwordController.text, ); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("비밀번호가 성공적으로 변경되었습니다. 다시 로그인해주세요."), backgroundColor: Colors.green, ), ); context.go('/login'); } } catch (e) { if (mounted) { _showError("비밀번호 변경에 실패했습니다: ${e.toString()}"); } } finally { if (mounted) { setState(() => _isLoading = false); } } } void _showError(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message), backgroundColor: Colors.red), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("새 비밀번호 설정"), centerTitle: true, ), body: Center( child: Container( constraints: const BoxConstraints(maxWidth: 400), padding: const EdgeInsets.all(24), child: _loginId == null || _loginId!.isEmpty ? _buildInvalidTokenView() : Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( "새로운 비밀번호 설정", style: GoogleFonts.outfit( fontSize: 28, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 16), const Text( "비밀번호는 최소 8자 이상이어야 하며,\n대소문자, 숫자, 특수문자를 모두 포함해야 합니다.", textAlign: TextAlign.center, style: TextStyle(color: Colors.grey), ), const SizedBox(height: 40), TextFormField( controller: _passwordController, obscureText: _isPasswordObscured, decoration: InputDecoration( labelText: "새 비밀번호", border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.lock_outline), suffixIcon: IconButton( icon: Icon( _isPasswordObscured ? Icons.visibility_off : Icons.visibility, ), onPressed: () { setState(() { _isPasswordObscured = !_isPasswordObscured; }); }, ), ), validator: (value) { if (value == null || value.isEmpty) { return '비밀번호를 입력해주세요.'; } if (value.length < 8) { return '비밀번호는 8자 이상이어야 합니다.'; } if (!RegExp(r'(?=.*[a-z])').hasMatch(value)) { return '최소 1개 이상의 소문자를 포함해야 합니다.'; } if (!RegExp(r'(?=.*[A-Z])').hasMatch(value)) { return '최소 1개 이상의 대문자를 포함해야 합니다.'; } if (!RegExp(r'(?=.*\d)').hasMatch(value)) { return '최소 1개 이상의 숫자를 포함해야 합니다.'; } if (!RegExp(r'(?=.*[\W_])').hasMatch(value)) { return '최소 1개 이상의 특수문자를 포함해야 합니다.'; } return null; }, ), const SizedBox(height: 16), TextFormField( controller: _confirmPasswordController, obscureText: _isConfirmPasswordObscured, decoration: InputDecoration( labelText: "새 비밀번호 확인", border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.lock_outline), suffixIcon: IconButton( icon: Icon( _isConfirmPasswordObscured ? Icons.visibility_off : Icons.visibility, ), onPressed: () { setState(() { _isConfirmPasswordObscured = !_isConfirmPasswordObscured; }); }, ), ), validator: (value) { if (value != _passwordController.text) { return '비밀번호가 일치하지 않습니다.'; } return null; }, ), const SizedBox(height: 24), FilledButton( onPressed: _isLoading ? null : _handlePasswordReset, style: FilledButton.styleFrom( minimumSize: const Size.fromHeight(50), ), child: _isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white), ) : const Text("비밀번호 변경"), ), ], ), ), ), ), ); } Widget _buildInvalidTokenView() { return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.error_outline, color: Colors.red, size: 60), SizedBox(height: 16), Text( "유효하지 않은 링크입니다.", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), SizedBox(height: 8), Text( "비밀번호 재설정 링크가 만료되었거나 잘못되었습니다. 다시 시도해주세요.", textAlign: TextAlign.center, ), ], ), ); } }