import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:intl/intl.dart'; import '../../core/services/chit_group_service.dart'; import '../../core/services/api_service.dart'; import '../../core/models/monthly_draw.dart'; import '../../core/utils/snackbar_util.dart'; class EditDrawDialog extends StatefulWidget { final MonthlyDraw draw; const EditDrawDialog({ super.key, required this.draw, }); @override State createState() => _EditDrawDialogState(); } class _EditDrawDialogState extends State { final _formKey = GlobalKey(); final _prizeAmountController = TextEditingController(); final _notesController = TextEditingController(); final _apiService = ApiService(); String? _selectedMemberId; bool _isLoading = false; late int _editMonth; late int _editYear; late DateTime _drawDate; static const _monthNames = [ '', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; DateTime _baselineDrawDate() { final d = widget.draw.drawDate; if (d.millisecondsSinceEpoch == 0) { return DateTime(widget.draw.year, widget.draw.month, 1); } return d; } bool _sameCalendarDay(DateTime a, DateTime b) { return a.year == b.year && a.month == b.month && a.day == b.day; } int _clampEditYear(int y) { final minY = 2020; final maxY = DateTime.now().year + 1; if (y < minY) return minY; if (y > maxY) return maxY; return y; } @override void initState() { super.initState(); _selectedMemberId = widget.draw.winnerId; _prizeAmountController.text = widget.draw.prizeAmount.toStringAsFixed(0); _notesController.text = widget.draw.notes ?? ''; _editMonth = widget.draw.month.clamp(1, 12); _editYear = _clampEditYear(widget.draw.year); _drawDate = _baselineDrawDate(); } @override void dispose() { _prizeAmountController.dispose(); _notesController.dispose(); super.dispose(); } Future _pickDrawDate() async { final picked = await showDatePicker( context: context, initialDate: _drawDate, firstDate: DateTime(2020), lastDate: DateTime.now().add(const Duration(days: 365 * 3)), ); if (picked != null) { setState(() => _drawDate = picked); } } Future _handleSubmit() async { if (_formKey.currentState!.validate()) { if (_selectedMemberId == null) { SnackbarUtil.showError('Please select a winner'); return; } setState(() => _isLoading = true); try { final updates = {}; if (_editMonth != widget.draw.month) { updates['month'] = _editMonth; } if (_editYear != widget.draw.year) { updates['year'] = _editYear; } if (!_sameCalendarDay(_drawDate, _baselineDrawDate())) { updates['draw_date'] = _drawDate.toUtc().toIso8601String(); } if (_selectedMemberId != widget.draw.winnerId) { updates['winner_id'] = _selectedMemberId; } final newPrizeAmount = double.parse(_prizeAmountController.text); if (newPrizeAmount != widget.draw.prizeAmount) { updates['prize_amount'] = newPrizeAmount; } if (_notesController.text != (widget.draw.notes ?? '')) { updates['notes'] = _notesController.text; } if (updates.isEmpty) { SnackbarUtil.showWarning('No changes made'); Get.back(); return; } final response = await _apiService.updateMonthlyDraw(widget.draw.id, updates); if (response['success']) { SnackbarUtil.showSuccess( 'Draw updated successfully', title: 'Success', ); Get.back(result: true); } else { final isAlreadyWon = response['alreadyWon'] ?? false; final winnerName = response['winnerName'] ?? ''; if (isAlreadyWon && winnerName.isNotEmpty) { SnackbarUtil.showError( '$winnerName has already won in another draw.\nEach member can only win once.', title: 'Duplicate winner', duration: const Duration(seconds: 4), ); } else { SnackbarUtil.showError( response['message'] ?? 'Failed to update draw', title: 'Error', ); } } } catch (e) { SnackbarUtil.showError('Error: ${e.toString()}'); } finally { setState(() => _isLoading = false); } } } @override Widget build(BuildContext context) { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.r)), child: Container( width: 500.w, constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.85, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Fixed Header Container( padding: EdgeInsets.all(24.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(20.r), topRight: Radius.circular(20.r), ), border: Border( bottom: BorderSide(color: Colors.grey.shade200), ), ), child: Row( children: [ Icon(Icons.edit, color: Colors.orange.shade600, size: 28.w), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Edit Draw Result', style: TextStyle( fontSize: 20.sp, fontWeight: FontWeight.bold, ), ), Text( 'Originally ${widget.draw.month}/${widget.draw.year}', style: TextStyle( fontSize: 14.sp, color: Colors.grey.shade600, ), ), ], ), ), IconButton( icon: const Icon(Icons.close), onPressed: () => Get.back(), ), ], ), ), // Scrollable Content Flexible( child: SingleChildScrollView( padding: EdgeInsets.all(24.w), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Warning Message Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: Colors.orange.shade50, borderRadius: BorderRadius.circular(12.r), border: Border.all(color: Colors.orange.shade200), ), child: Row( children: [ Icon(Icons.warning_amber_rounded, color: Colors.orange.shade700, size: 24.w), SizedBox(width: 12.w), Expanded( child: Text( 'Carefully verify changes before saving. This will update the official draw record.', style: TextStyle( color: Colors.orange.shade900, fontSize: 14.sp, fontWeight: FontWeight.w500, ), ), ), ], ), ), SizedBox(height: 24.h), Text( 'Draw month & year', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 8.h), Row( children: [ Expanded( child: DropdownButtonFormField( value: _editMonth, decoration: InputDecoration( labelText: 'Month', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12.r), ), filled: true, fillColor: Colors.grey.shade50, ), items: List.generate(12, (i) { final m = i + 1; return DropdownMenuItem( value: m, child: Text('${_monthNames[m]} ($m)'), ); }), onChanged: (v) { if (v != null) setState(() => _editMonth = v); }, ), ), SizedBox(width: 12.w), Expanded( child: DropdownButtonFormField( value: _editYear, decoration: InputDecoration( labelText: 'Year', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12.r), ), filled: true, fillColor: Colors.grey.shade50, ), items: List.generate( DateTime.now().year - 2019 + 2, (i) { final y = 2020 + i; return DropdownMenuItem( value: y, child: Text('$y'), ); }, ), onChanged: (v) { if (v != null) setState(() => _editYear = v); }, ), ), ], ), SizedBox(height: 8.h), Text( 'This is the calendar month this draw belongs to. It must not clash with another draw in this group.', style: TextStyle(fontSize: 12.sp, color: Colors.grey.shade600), ), SizedBox(height: 20.h), Text( 'Draw date', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 8.h), InkWell( onTap: _pickDrawDate, borderRadius: BorderRadius.circular(12.r), child: InputDecorator( decoration: InputDecoration( prefixIcon: const Icon(Icons.calendar_today_outlined), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12.r), ), filled: true, fillColor: Colors.grey.shade50, ), child: Text( DateFormat('d MMM yyyy').format(_drawDate), style: TextStyle(fontSize: 16.sp), ), ), ), SizedBox(height: 8.h), Text( 'When the draw actually happened (shown in history).', style: TextStyle(fontSize: 12.sp, color: Colors.grey.shade600), ), SizedBox(height: 20.h), // Select Winner Text( 'Winner', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 12.h), Obx(() { final members = Get.find().groupMembers; if (members.isEmpty) { return Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(12.r), ), child: Text( 'Loading members...', style: TextStyle( color: Colors.grey.shade600, fontSize: 14.sp, ), ), ); } return Container( constraints: BoxConstraints( maxHeight: 250.h, ), decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(12.r), ), child: ListView.builder( shrinkWrap: true, itemCount: members.length, itemBuilder: (context, index) { final member = members[index]; final isSelected = member.userId == _selectedMemberId; final isCurrentWinner = member.userId == widget.draw.winnerId; final isLast = index == members.length - 1; return InkWell( onTap: () { setState(() { _selectedMemberId = member.userId; }); }, borderRadius: BorderRadius.vertical( top: index == 0 ? Radius.circular(12.r) : Radius.zero, bottom: isLast ? Radius.circular(12.r) : Radius.zero, ), child: Container( padding: EdgeInsets.symmetric( horizontal: 12.w, vertical: 14.h, ), decoration: BoxDecoration( color: isSelected ? Colors.green.shade50 : null, border: !isLast ? Border( bottom: BorderSide(color: Colors.grey.shade200), ) : null, ), child: Row( children: [ Icon( isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, color: isSelected ? Colors.green.shade600 : Colors.grey.shade400, size: 24.w, ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( member.user?.fullName ?? 'Unknown', style: TextStyle( fontSize: 16.sp, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), ), ), if (isCurrentWinner) ...[ Container( padding: EdgeInsets.symmetric( horizontal: 6.w, vertical: 2.h, ), decoration: BoxDecoration( color: Colors.blue.shade100, borderRadius: BorderRadius.circular(4.r), ), child: Text( 'Current', style: TextStyle( fontSize: 10.sp, color: Colors.blue.shade800, fontWeight: FontWeight.w600, ), ), ), ], ], ), if (member.user?.mobileNumber != null) ...[ SizedBox(height: 2.h), Text( member.user!.mobileNumber, style: TextStyle( fontSize: 13.sp, color: Colors.grey.shade600, ), ), ], ], ), ), if (isSelected) Icon(Icons.check_circle, color: Colors.green.shade600, size: 20.w), ], ), ), ); }, ), ); }), SizedBox(height: 20.h), // Prize Amount Text( 'Prize Amount', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 8.h), TextFormField( controller: _prizeAmountController, keyboardType: TextInputType.number, decoration: InputDecoration( hintText: 'Prize amount', prefixText: '₹ ', prefixIcon: const Icon(Icons.currency_rupee), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12.r), ), filled: true, fillColor: Colors.grey.shade50, ), validator: (value) { if (value?.isEmpty ?? true) return 'Required'; if (double.tryParse(value!) == null) return 'Invalid amount'; return null; }, ), SizedBox(height: 20.h), // Notes (Optional) Text( 'Notes (Optional)', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 8.h), TextFormField( controller: _notesController, maxLines: 3, decoration: InputDecoration( hintText: 'Reason for editing (optional)', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12.r), ), filled: true, fillColor: Colors.grey.shade50, ), ), ], ), ), ), ), // Fixed Footer with Actions Container( padding: EdgeInsets.all(24.w), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( bottomLeft: Radius.circular(20.r), bottomRight: Radius.circular(20.r), ), border: Border( top: BorderSide(color: Colors.grey.shade200), ), ), child: Row( children: [ Expanded( child: OutlinedButton( onPressed: _isLoading ? null : () => Get.back(), style: OutlinedButton.styleFrom( padding: EdgeInsets.symmetric(vertical: 14.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.r), ), ), child: Text( 'Cancel', style: TextStyle(fontSize: 16.sp), ), ), ), SizedBox(width: 16.w), Expanded( child: ElevatedButton( onPressed: _isLoading ? null : _handleSubmit, style: ElevatedButton.styleFrom( backgroundColor: Colors.orange.shade600, foregroundColor: Colors.white, padding: EdgeInsets.symmetric(vertical: 14.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.r), ), elevation: 2, ), child: _isLoading ? SizedBox( height: 20.h, width: 20.w, child: const CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : Text( 'Update Draw', style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600), ), ), ), ], ), ), ], ), ), ); } }