import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:login_vault_app/auth_service.dart'; import 'package:login_vault_app/dashboard_screen.dart'; import 'package:login_vault_app/theme_provider.dart'; /// First screen: register (if not yet), or re-authenticate (if registered). /// If a valid session exists, skip straight to the Dashboard. class AuthScreen extends StatefulWidget { final AuthService auth; const AuthScreen({super.key, required this.auth}); @override State createState() => _AuthScreenState(); } class _AuthScreenState extends State { final _emailCtrl = TextEditingController(); final _passCtrl = TextEditingController(); bool _isLogin = true; bool _busy = false; String? _error; String? _bioMsg; bool _biometricAvailable = false; bool _biometricEnabled = false; @override void initState() { super.initState(); _initMode(); } /// Decide login vs register based on whether an account exists. Future _initMode() async { final registered = await widget.auth.isRegistered(); if (!mounted) return; final avail = await widget.auth.canUseBiometrics(); final enabled = await widget.auth.isBiometricEnabled(); setState(() { _isLogin = registered; _biometricAvailable = avail; _biometricEnabled = enabled; }); // If already registered and biometric is enabled, prompt fingerprint // automatically (unless a valid session already skips to dashboard). if (registered && enabled) { final timeout = await widget.auth.getTimeoutMinutes(); final valid = await widget.auth.hasValidSession(timeout); if (!valid) { _promptBiometricOnOpen(); return; // skip silent-auth path; biometric handles entry } } _trySilentAuth(); } /// Auto-prompt fingerprint on open when enabled; on success go to dashboard /// (email may be empty for google-less accounts, fallback to stored email). Future _promptBiometricOnOpen() async { final (ok, err) = await widget.auth.authenticateWithBiometrics(); if (!mounted) return; if (ok) { final email = await widget.auth.getEmail() ?? ''; _goToDashboard(email); } else { // fingerprint failed/cancelled -> let user login manually setState(() { _bioMsg = 'Gagal verifikasi sidik jari. Silakan masuk manual.'; }); } } /// On open: if a valid session is present, go straight to Dashboard. Future _trySilentAuth() async { final timeout = await widget.auth.getTimeoutMinutes(); final valid = await widget.auth.hasValidSession(timeout); if (valid && mounted) { final email = await widget.auth.getEmail() ?? ''; _goToDashboard(email); } } void _goToDashboard(String email) { if (!mounted) return; widget.auth.openSession(); // refresh session timestamp Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (_) => DashboardScreen( auth: widget.auth, theme: Provider.of(context, listen: false), email: email, ), ), ); } Future _submit() async { setState(() => _busy = true); final email = _emailCtrl.text.trim(); final pass = _passCtrl.text; if (email.isEmpty || pass.isEmpty) { setState(() => _error = 'Email & password wajib diisi'); _busy = false; return; } try { if (_isLogin) { final stored = await widget.auth.getAppPassword(); final ok = await widget.auth.verifyPassword(pass); if (stored == null) { setState(() => _error = 'Belum terdaftar, silakan registrasi'); } else if (!ok) { setState(() => _error = 'Password aplikasi salah'); } else { _goToDashboard(email); } } else { await widget.auth.registerWithEmail(email, pass); _goToDashboard(email); } } catch (e) { setState(() => _error = e.toString()); } finally { if (mounted) setState(() => _busy = false); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Login Vault')), body: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(_isLogin ? 'Masuk' : 'Daftar', style: Theme.of(context).textTheme.headlineSmall), const SizedBox(height: 16), TextField( controller: _emailCtrl, keyboardType: TextInputType.emailAddress, decoration: const InputDecoration( labelText: 'Email', border: OutlineInputBorder()), ), const SizedBox(height: 12), TextField( controller: _passCtrl, obscureText: true, decoration: const InputDecoration( labelText: 'Password aplikasi', border: OutlineInputBorder()), ), const SizedBox(height: 8), if (_error != null) Text(_error!, style: const TextStyle(color: Colors.red)), if (_bioMsg != null) Padding( padding: const EdgeInsets.only(bottom: 8), child: Text(_bioMsg!, style: const TextStyle(color: Colors.grey)), ), const SizedBox(height: 12), _busy ? const CircularProgressIndicator() : Column( children: [ ElevatedButton( onPressed: _submit, child: Text(_isLogin ? 'Masuk' : 'Daftar'), ), // Biometric retry button (only when enabled + registered) if (_isLogin && _biometricAvailable && _biometricEnabled) TextButton.icon( onPressed: () { setState(() => _bioMsg = null); _promptBiometricOnOpen(); }, icon: const Icon(Icons.fingerprint), label: const Text('Gunakan Sidik Jari'), ), ], ), ], ), ), ); } }