import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:purchases_flutter/purchases_flutter.dart'; import 'package:cid_app/services/subscription_service.dart'; class PaywallScreen extends StatefulWidget { final VoidCallback onSuccess; const PaywallScreen({super.key, required this.onSuccess}); @override State createState() => _PaywallScreenState(); } class _PaywallScreenState extends State with SingleTickerProviderStateMixin { Package? _yearlyPackage; bool _isLoading = true; bool _isPurchasing = false; late AnimationController _animationController; late Animation _fadeAnimation; @override void initState() { super.initState(); _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 800)); _fadeAnimation = CurvedAnimation(parent: _animationController, curve: Curves.easeOut); _fetchOffers(); _animationController.forward(); } Future _fetchOffers() async { final offerings = await SubscriptionService.fetchOfferings(); if (offerings != null && offerings.current != null) { setState(() { // Cerchiamo il pacchetto annuale _yearlyPackage = offerings.current!.annual; _isLoading = false; }); } else { setState(() { _isLoading = false; }); } } Future _buyPackage() async { if (_yearlyPackage == null) return; setState(() { _isPurchasing = true; }); final success = await SubscriptionService.purchasePackage(_yearlyPackage!); if (mounted) { setState(() { _isPurchasing = false; }); if (success) { widget.onSuccess(); Navigator.of(context).pop(); // Chiude il paywall in caso di successo } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Acquisto annullato o non andato a buon fine.')), ); } } } Future _restorePurchases() async { setState(() { _isPurchasing = true; }); final success = await SubscriptionService.restorePurchases(); if (mounted) { setState(() { _isPurchasing = false; }); if (success) { widget.onSuccess(); Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Acquisti ripristinati con successo! Bentornato.')), ); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Nessun abbonamento attivo trovato su questo account.')), ); } } } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, // Sfondo scuro elegante body: Stack( children: [ // Sfondo con gradienti animati (Simulato staticamente qui per performance) Positioned.fill( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF1E3A8A), Color(0xFF0F172A)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), ), ), // Decorazione circolare sfocata Positioned( top: -100, right: -50, child: Container( width: 300, height: 300, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.blueAccent.withValues(alpha: 0.3), ), ), ), Positioned( bottom: -50, left: -100, child: Container( width: 300, height: 300, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.purpleAccent.withValues(alpha: 0.2), ), ), ), // Blur globale Positioned.fill( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50), child: Container(color: Colors.transparent), ), ), // Contenuto Principale SafeArea( child: FadeTransition( opacity: _fadeAnimation, child: SingleChildScrollView( physics: const BouncingScrollPhysics(), child: Column( children: [ Align( alignment: Alignment.topRight, child: IconButton( icon: const Icon(Icons.close, color: Colors.white70), onPressed: () => Navigator.of(context).pop(), ), ), const SizedBox(height: 10), const Icon(Icons.qr_code_scanner_rounded, size: 80, color: Colors.white), const SizedBox(height: 20), const Text( 'Sblocca la Sincronizzazione', style: TextStyle( color: Colors.white, fontSize: 28, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), textAlign: TextAlign.center, ), const SizedBox(height: 15), const Padding( padding: EdgeInsets.symmetric(horizontal: 40), child: Text( 'Unisci i dati dei due veicoli in un istante e genera il CID PDF valido ai fini assicurativi.', style: TextStyle( color: Colors.white70, fontSize: 16, height: 1.5, ), textAlign: TextAlign.center, ), ), const SizedBox(height: 40), // Card Glassmorphism Container( margin: const EdgeInsets.symmetric(horizontal: 30), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(20), border: Border.all(color: Colors.white.withValues(alpha: 0.2)), ), child: Column( children: [ _buildFeatureRow(Icons.check_circle, 'Scansione QR Code istantanea'), const SizedBox(height: 12), _buildFeatureRow(Icons.check_circle, 'Generazione PDF Ufficiale'), const SizedBox(height: 12), _buildFeatureRow(Icons.check_circle, 'Nessuna Pubblicità'), ], ), ), const SizedBox(height: 40), // Bottone Acquisto if (_isLoading) const CircularProgressIndicator(color: Colors.white) else if (_yearlyPackage != null) Padding( padding: const EdgeInsets.symmetric(horizontal: 30), child: ElevatedButton( onPressed: _isPurchasing ? null : _buyPackage, style: ElevatedButton.styleFrom( backgroundColor: Colors.blueAccent, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ), elevation: 10, shadowColor: Colors.blueAccent.withValues(alpha: 0.5), minimumSize: const Size(double.infinity, 55), ), child: _isPurchasing ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2), ) : Text( 'Passa a PRO - ${_yearlyPackage!.storeProduct.priceString} / anno', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), ), ) else const Text('Pacchetti non disponibili. Riprova più tardi.', style: TextStyle(color: Colors.redAccent)), const SizedBox(height: 20), // Tasto Ripristina TextButton( onPressed: _isPurchasing ? null : _restorePurchases, child: const Text( 'Hai già un abbonamento? Ripristina acquisti', style: TextStyle(color: Colors.white70, decoration: TextDecoration.underline), ), ), const SizedBox(height: 30), // Footer Legale (Obbligatorio per Apple) Padding( padding: const EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( onPressed: () { /* TODO Apri Terms */ }, child: const Text('Terms of Use', style: TextStyle(color: Colors.white54, fontSize: 12)), ), const Text('|', style: TextStyle(color: Colors.white54, fontSize: 12)), TextButton( onPressed: () { /* TODO Apri Privacy */ }, child: const Text('Privacy Policy', style: TextStyle(color: Colors.white54, fontSize: 12)), ), ], ), ), ], ), ), ), ), ], ), ); } Widget _buildFeatureRow(IconData icon, String text) { return Row( children: [ Icon(icon, color: Colors.greenAccent, size: 24), const SizedBox(width: 15), Expanded( child: Text( text, style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500), ), ), ], ); } }