import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../services/entitlements/entitlement_providers.dart'; import '../../../services/entitlements/feature_access_service.dart'; import '../../rides/ride_state_machine.dart'; /// Small inline badge indicating a Pro-only feature. /// Follows MotorSignal cockpit aesthetic (dark surface, subtle cyan accent, no neon glow). class ProBadge extends StatelessWidget { final double fontSize; final EdgeInsetsGeometry padding; const ProBadge({ super.key, this.fontSize = 9, this.padding = const EdgeInsets.symmetric(horizontal: 6, vertical: 2), }); @override Widget build(BuildContext context) { return Container( padding: padding, decoration: BoxDecoration( color: const Color(0xFF00E5FF).withValues(alpha: 0.15), borderRadius: BorderRadius.circular(4), border: Border.all( color: const Color(0xFF00E5FF).withValues(alpha: 0.6), width: 0.8, ), ), child: Text( 'PRO', style: TextStyle( fontFamily: 'Inter', fontSize: fontSize, fontWeight: FontWeight.w900, color: const Color(0xFF00E5FF), letterSpacing: 0.8, ), ), ); } } /// Metadata description helper for MotorSignal features. class FeatureBenefitInfo { final String title; final String description; final IconData icon; const FeatureBenefitInfo({ required this.title, required this.description, required this.icon, }); static FeatureBenefitInfo forFeature(MotorSignalFeature feature) { switch (feature) { case MotorSignalFeature.cloudBackup: case MotorSignalFeature.unlimitedCloudHistory: return const FeatureBenefitInfo( title: 'Unlimited MotorCloud Sync', description: 'Automatically preserve your entire ride catalog, telemetry, and motorcycle configurations to MotorCloud.', icon: Icons.cloud_done_outlined, ); case MotorSignalFeature.multiDeviceRestore: return const FeatureBenefitInfo( title: 'Multi-Device Cloud Restore', description: 'Seamlessly sync your complete ride records and garage to new phones or secondary devices.', icon: Icons.devices_outlined, ); case MotorSignalFeature.advancedTelemetry: case MotorSignalFeature.advancedAnalytics: return const FeatureBenefitInfo( title: 'Advanced Telemetry & Analytics', description: 'Deep sensor analysis including 20Hz telemetry graphs, elevation profiles, and cornering metrics.', icon: Icons.show_chart, ); case MotorSignalFeature.advancedAcceleration: return const FeatureBenefitInfo( title: 'Advanced Acceleration Analysis', description: 'Analyze longitudinal acceleration forces, sprint splits, and throttle roll-on dynamics.', icon: Icons.speed, ); case MotorSignalFeature.advancedBraking: return const FeatureBenefitInfo( title: 'Advanced Braking Analysis', description: 'Detailed braking G-force thresholds, trail-braking telemetry, and stopping deceleration.', icon: Icons.disc_full_outlined, ); case MotorSignalFeature.advancedLean: return const FeatureBenefitInfo( title: 'Advanced Lean Angle Analysis', description: 'Comprehensive left/right apex lean angle distribution, transition rate, and corner stability.', icon: Icons.screen_rotation, ); case MotorSignalFeature.unlimitedHistory: return const FeatureBenefitInfo( title: 'Unlimited Ride History', description: 'Keep a permanent, searchable ledger of every ride you record without duration caps.', icon: Icons.history, ); case MotorSignalFeature.csvExport: case MotorSignalFeature.pdfExport: return const FeatureBenefitInfo( title: 'Forensic CSV & PDF Export', description: 'Export sub-second 20Hz forensic data tables and printable performance reports.', icon: Icons.table_chart_outlined, ); case MotorSignalFeature.useMultipleMotorcycles: return const FeatureBenefitInfo( title: 'Multiple Motorcycle Garage', description: 'Manage your full fleet with motorcycle-specific geometry, specs, and ride logs.', icon: Icons.two_wheeler, ); case MotorSignalFeature.planTrips: return const FeatureBenefitInfo( title: 'Advanced Route & Trip Planning', description: 'Plan multi-waypoint tours, fuel stops, and twisty scenic routing.', icon: Icons.alt_route, ); case MotorSignalFeature.createGroupRides: case MotorSignalFeature.useAdvancedGroupRideFeatures: return const FeatureBenefitInfo( title: 'Advanced Group Riding', description: 'Coordinate organized pack rides with real-time route progress and rendezvous points.', icon: Icons.group_work_outlined, ); } } } /// Helper to trigger a contextual Pro upgrade sheet. /// STRICT RIDER SAFETY GUARANTEE: /// If the rider is currently riding (active ride recording or moving), this modal is SUPPRESSED /// and replaced with an unobtrusive passive toast to prevent screen distraction. Future showProUpgradeSheet( BuildContext context, WidgetRef ref, { required MotorSignalFeature feature, }) async { final session = ref.read(rideStateMachineProvider); final isRiding = session.state == RideState.riding; if (isRiding) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Pro feature locked. Upgrade available when stopped.'), duration: Duration(seconds: 2), ), ); return; } final info = FeatureBenefitInfo.forFeature(feature); await showModalBottomSheet( context: context, backgroundColor: const Color(0xFF0F0F0F), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), builder: (ctx) { return SafeArea( child: Padding( padding: const EdgeInsets.all(20.0), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: const Color(0xFF00E5FF).withValues(alpha: 0.12), borderRadius: BorderRadius.circular(10), ), child: Icon( info.icon, color: const Color(0xFF00E5FF), size: 24, ), ), const SizedBox(width: 14), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Flexible( child: Text( info.title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), const SizedBox(width: 8), const ProBadge(), ], ), const SizedBox(height: 2), const Text( 'MotorSignal Pro Feature', style: TextStyle(fontSize: 11, color: Colors.white54), ), ], ), ), ], ), const SizedBox(height: 16), Text( info.description, style: const TextStyle( fontSize: 13, color: Colors.white70, height: 1.4, ), ), const SizedBox(height: 24), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF00E5FF), foregroundColor: Colors.black, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), onPressed: () { Navigator.of(ctx).pop(); context.push('/pro'); }, child: const Text( 'VIEW MOTORSIGNAL PRO', style: TextStyle( fontWeight: FontWeight.bold, letterSpacing: 1.0, ), ), ), const SizedBox(height: 10), TextButton( style: TextButton.styleFrom(foregroundColor: Colors.white60), onPressed: () => Navigator.of(ctx).pop(), child: const Text('NOT NOW'), ), ], ), ), ); }, ); } /// Reusable inline locked feature row. class ProLockedRow extends ConsumerWidget { final MotorSignalFeature feature; final Widget title; final Widget? subtitle; final Widget? leading; const ProLockedRow({ super.key, required this.feature, required this.title, this.subtitle, this.leading, }); @override Widget build(BuildContext context, WidgetRef ref) { final featureAccess = ref.watch(featureAccessProvider); final hasAccess = featureAccess.canAccess(feature); if (hasAccess) { return const SizedBox.shrink(); } return InkWell( onTap: () => showProUpgradeSheet(context, ref, feature: feature), child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0), child: Row( children: [ if (leading != null) ...[leading!, const SizedBox(width: 12)], Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Flexible(child: title), const SizedBox(width: 6), const ProBadge(), ], ), if (subtitle != null) ...[ const SizedBox(height: 2), subtitle!, ], ], ), ), const Icon(Icons.lock_outline, size: 18, color: Colors.white38), ], ), ), ); } }