import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../models/motorcycle_models.dart'; import 'garage_providers.dart'; class AddMotorcycleScreen extends ConsumerStatefulWidget { const AddMotorcycleScreen({super.key}); @override ConsumerState createState() => _AddMotorcycleScreenState(); } class _AddMotorcycleScreenState extends ConsumerState { int _step = 1; // 1: Year, 2: Make, 3: Model, 4: Variant, 5: Confirm int? _selectedYear; MotorcycleMake? _selectedMake; MotorcycleModel? _selectedModel; MotorcycleVariant? _selectedVariant; MotorcycleSpecification? _previewSpec; final TextEditingController _nicknameController = TextEditingController(); final TextEditingController _searchController = TextEditingController(); bool _isLoading = false; List _years = []; List _makes = []; List _models = []; List _variants = []; @override void initState() { super.initState(); _loadYears(); } @override void dispose() { _nicknameController.dispose(); _searchController.dispose(); super.dispose(); } Future _loadYears() async { setState(() => _isLoading = true); final repo = ref.read(motorcycleRepositoryProvider); final years = await repo.getYears(); setState(() { _years = years; _isLoading = false; }); } Future _selectYear(int year) async { setState(() { _selectedYear = year; _step = 2; _isLoading = true; _searchController.clear(); }); final repo = ref.read(motorcycleRepositoryProvider); final makes = await repo.getMakes(year); setState(() { _makes = makes; _isLoading = false; }); } Future _selectMake(MotorcycleMake make) async { setState(() { _selectedMake = make; _step = 3; _isLoading = true; _searchController.clear(); }); final repo = ref.read(motorcycleRepositoryProvider); final models = await repo.getModels(_selectedYear!, make.id); setState(() { _models = models; _isLoading = false; }); } Future _selectModel(MotorcycleModel model) async { setState(() { _selectedModel = model; _isLoading = true; }); final repo = ref.read(motorcycleRepositoryProvider); final variants = await repo.getVariants(_selectedYear!, _selectedMake!.id, model.id); if (variants.length <= 1) { _selectedVariant = variants.isNotEmpty ? variants.first : null; await _loadSpecSummary(); } else { setState(() { _variants = variants; _step = 4; _isLoading = false; }); } } Future _selectVariant(MotorcycleVariant variant) async { setState(() { _selectedVariant = variant; }); await _loadSpecSummary(); } Future _loadSpecSummary() async { setState(() => _isLoading = true); final selection = MotorcycleSelection( year: _selectedYear!, makeId: _selectedMake!.id, makeName: _selectedMake!.name, modelId: _selectedModel!.id, modelName: _selectedModel!.name, variantId: _selectedVariant?.id, variantName: _selectedVariant?.name, ); final repo = ref.read(motorcycleRepositoryProvider); final spec = await repo.getSpecifications(selection); setState(() { _previewSpec = spec; _step = 5; _isLoading = false; }); } Future _saveMotorcycle() async { final selection = MotorcycleSelection( year: _selectedYear!, makeId: _selectedMake!.id, makeName: _selectedMake!.name, modelId: _selectedModel!.id, modelName: _selectedModel!.name, variantId: _selectedVariant?.id, variantName: _selectedVariant?.name, ); final controller = ref.read(garageControllerProvider); await controller.addMotorcycle( selection, nickname: _nicknameController.text.trim().isNotEmpty ? _nicknameController.text.trim() : null, ); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Added ${selection.displayName} to your Garage!')), ); context.pop(); } } void _goBack() { if (_step > 1) { setState(() { _step -= 1; _searchController.clear(); }); } else { context.pop(); } } @override Widget build(BuildContext context) { return PopScope( canPop: _step == 1, onPopInvokedWithResult: (didPop, result) { if (!didPop && _step > 1) { _goBack(); } }, child: Scaffold( appBar: AppBar( title: Text(_getStepTitle()), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: _goBack, ), ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : Column( children: [ LinearProgressIndicator(value: _step / 5.0, backgroundColor: Colors.white10, valueColor: const AlwaysStoppedAnimation(Colors.cyanAccent)), Expanded(child: _buildStepContent()), ], ), ), ); } String _getStepTitle() { switch (_step) { case 1: return 'Select Year'; case 2: return 'Select Manufacturer'; case 3: return 'Select Model (${_selectedMake?.name ?? ""})'; case 4: return 'Select Variant'; case 5: return 'Confirm Motorcycle'; default: return 'Add Motorcycle'; } } Widget _buildStepContent() { switch (_step) { case 1: return _buildYearStep(); case 2: return _buildMakeStep(); case 3: return _buildModelStep(); case 4: return _buildVariantStep(); case 5: return _buildConfirmStep(); default: return const SizedBox(); } } Widget _buildYearStep() { return GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, childAspectRatio: 2.2, crossAxisSpacing: 10, mainAxisSpacing: 10, ), itemCount: _years.length, itemBuilder: (context, index) { final year = _years[index].year; return OutlinedButton( style: OutlinedButton.styleFrom( side: BorderSide(color: _selectedYear == year ? Colors.cyanAccent : Colors.white24), backgroundColor: _selectedYear == year ? Colors.cyanAccent.withValues(alpha: 0.2) : null, ), onPressed: () => _selectYear(year), child: Text('$year', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: Colors.white)), ); }, ); } Widget _buildMakeStep() { final query = _searchController.text.toLowerCase(); final filtered = _makes.where((m) => m.name.toLowerCase().contains(query)).toList(); return Column( children: [ Padding( padding: const EdgeInsets.all(16.0), child: TextField( controller: _searchController, decoration: InputDecoration( hintText: 'Search Manufacturer...', prefixIcon: const Icon(Icons.search, color: Colors.cyanAccent), filled: true, fillColor: Colors.white10, border: OutlineInputBorder(borderRadius: BorderRadius.circular(10), borderSide: BorderSide.none), ), onChanged: (_) => setState(() {}), ), ), Expanded( child: ListView.separated( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: filtered.length, separatorBuilder: (_, _) => const Divider(height: 1, color: Colors.white10), itemBuilder: (context, index) { final make = filtered[index]; return ListTile( title: Text(make.name, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 18)), trailing: const Icon(Icons.chevron_right, color: Colors.white30), onTap: () => _selectMake(make), ); }, ), ), ], ); } Widget _buildModelStep() { final query = _searchController.text.toLowerCase(); final filtered = _models.where((m) => m.name.toLowerCase().contains(query)).toList(); return Column( children: [ Padding( padding: const EdgeInsets.all(16.0), child: TextField( controller: _searchController, decoration: InputDecoration( hintText: 'Search Model...', prefixIcon: const Icon(Icons.search, color: Colors.cyanAccent), filled: true, fillColor: Colors.white10, border: OutlineInputBorder(borderRadius: BorderRadius.circular(10), borderSide: BorderSide.none), ), onChanged: (_) => setState(() {}), ), ), Expanded( child: ListView.separated( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: filtered.length, separatorBuilder: (_, _) => const Divider(height: 1, color: Colors.white10), itemBuilder: (context, index) { final model = filtered[index]; return ListTile( title: Text(model.name, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 18)), subtitle: Text('$_selectedYear ${_selectedMake?.name}'), trailing: const Icon(Icons.chevron_right, color: Colors.white30), onTap: () => _selectModel(model), ); }, ), ), ], ); } Widget _buildVariantStep() { return ListView.separated( padding: const EdgeInsets.all(16), itemCount: _variants.length, separatorBuilder: (_, _) => const SizedBox(height: 12), itemBuilder: (context, index) { final variant = _variants[index]; return Card( child: ListTile( title: Text(variant.name, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18)), trailing: const Icon(Icons.check_circle_outline, color: Colors.cyanAccent), onTap: () => _selectVariant(variant), ), ); }, ); } Widget _buildConfirmStep() { final spec = _previewSpec; return SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white10, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.cyanAccent, width: 2), ), child: Column( children: [ const Icon(Icons.two_wheeler, size: 64, color: Colors.cyanAccent), const SizedBox(height: 12), Text( '$_selectedYear ${_selectedMake?.name} ${_selectedModel?.name}', textAlign: TextAlign.center, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), if (_selectedVariant?.name != null && _selectedVariant!.name != 'Standard') ...[ const SizedBox(height: 4), Text(_selectedVariant!.name, style: const TextStyle(color: Colors.white70, fontSize: 16)), ], ], ), ), const SizedBox(height: 24), if (spec != null) ...[ const Text('SPECIFICATION SUMMARY', style: TextStyle(color: Colors.cyanAccent, fontWeight: FontWeight.bold, letterSpacing: 1.2)), const SizedBox(height: 12), Row( children: [ Expanded(child: _buildSpecChip('DISPLACEMENT', spec.displacementCc != null ? '${spec.displacementCc!.toStringAsFixed(0)} cc' : '—')), const SizedBox(width: 12), Expanded(child: _buildSpecChip('HORSEPOWER', spec.horsepower != null ? '${spec.horsepower!.toStringAsFixed(0)} HP' : '—')), ], ), const SizedBox(height: 12), Row( children: [ Expanded(child: _buildSpecChip('TORQUE', spec.torqueLbFt != null ? '${spec.torqueLbFt!.toStringAsFixed(1)} lb-ft' : '—')), const SizedBox(width: 12), Expanded(child: _buildSpecChip('WET WEIGHT', spec.wetWeightLbs != null ? '${spec.wetWeightLbs!.toStringAsFixed(0)} lbs' : '—')), ], ), const SizedBox(height: 24), ], TextField( controller: _nicknameController, decoration: InputDecoration( labelText: 'Nickname (Optional)', hintText: 'e.g., Blue Beast, The Track Bike', border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)), prefixIcon: const Icon(Icons.edit, color: Colors.cyanAccent), ), ), const SizedBox(height: 32), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.cyanAccent, foregroundColor: Colors.black, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ), onPressed: _saveMotorcycle, child: const Text('ADD TO GARAGE', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 1.5)), ), ], ), ); } Widget _buildSpecChip(String label, String value) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.05), borderRadius: BorderRadius.circular(10), border: Border.all(color: Colors.white12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle(fontSize: 10, color: Colors.white54, letterSpacing: 1.0)), const SizedBox(height: 4), Text(value, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white)), ], ), ); } }