import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:onsolgo/core/constants.dart'; import 'dart:math'; class AdminDashboard extends StatelessWidget { const AdminDashboard({super.key}); // --- LOGIC: SYSTEM BROADCAST --- void _editAnnouncement(BuildContext context) async { final tC = TextEditingController(); final mC = TextEditingController(); bool active = true; try { var existing = await FirebaseFirestore.instance.collection('system').doc('announcement').get(); if (existing.exists) { final map = existing.data(); if (map != null) { tC.text = map['title']?.toString() ?? ''; mC.text = map['message']?.toString() ?? ''; active = map['isActive'] as bool? ?? true; } } } catch (e) { debugPrint("Load Error: $e"); } if (!context.mounted) return; showDialog( context: context, builder: (ctx) => StatefulBuilder( builder: (ctx, setS) => AlertDialog( backgroundColor: Colors.grey[900], title: const Text("SYSTEM BROADCAST", style: TextStyle(color: kOnsolGold, fontSize: 14, fontWeight: FontWeight.bold)), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField(controller: tC, decoration: const InputDecoration(hintText: "Headline")), const SizedBox(height: 10), TextField(controller: mC, maxLines: 3, decoration: const InputDecoration(hintText: "Message")), SwitchListTile( title: const Text("Show Popup", style: TextStyle(fontSize: 12)), value: active, activeThumbColor: kOnsolGold, onChanged: (v) => setS(() => active = v) ), ], ), actions: [ TextButton(onPressed: () => Navigator.pop(ctx), child: const Text("CANCEL", style: TextStyle(color: Colors.grey))), ElevatedButton( onPressed: () async { await FirebaseFirestore.instance.collection('system').doc('announcement').set({ 'title': tC.text.trim(), 'message': mC.text.trim(), 'isActive': active, 'updatedAt': FieldValue.serverTimestamp() }); if (context.mounted) Navigator.pop(ctx); }, child: const Text("TRANSMIT"), ) ], ), ), ); } @override Widget build(BuildContext context) { return DefaultTabController( length: 4, child: Scaffold( backgroundColor: Colors.black, appBar: AppBar( backgroundColor: Colors.red[900], title: const Text("COMMAND CENTER", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)), actions: [ IconButton(icon: const Icon(Icons.podcasts), onPressed: () => _editAnnouncement(context)) ], bottom: const TabBar( labelStyle: TextStyle(fontSize: 8, fontWeight: FontWeight.bold), indicatorColor: Colors.white, tabs: [ Tab(text: "SERIES", icon: Icon(Icons.library_books, size: 18)), Tab(text: "MERCH", icon: Icon(Icons.shopping_bag, size: 18)), Tab(text: "CITIZENS", icon: Icon(Icons.people, size: 18)), Tab(text: "INVITES", icon: Icon(Icons.vpn_key, size: 18)), ], ), ), body: const TabBarView( children: [ _ManageSeriesTab(), _ManageMerchTab(), _ManageUsersTab(), _ManageInvitesTab(), ], ), ), ); } } // --- TAB 3: CITIZEN MODERATION (Energy & Ranks) --- class _ManageUsersTab extends StatelessWidget { const _ManageUsersTab(); void _showModeration(BuildContext context, DocumentSnapshot user) { var d = user.data() as Map; int rank = safeInt(d['rankLevel'] ?? 1); bool ver = d['isVerified'] ?? (rank == 5); bool ban = d['isBanned'] ?? false; showDialog( context: context, builder: (ctx) => StatefulBuilder( builder: (ctx, setS) => AlertDialog( backgroundColor: Colors.grey[900], title: Text("MODERATING: ${d['username'] ?? 'Citizen'}"), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ DropdownButton( value: rank, isExpanded: true, dropdownColor: Colors.black, items: [1, 2, 3, 4, 5].map((v) => DropdownMenuItem(value: v, child: Text(getRankName(v)))).toList(), onChanged: (v) => setS(() { rank = v!; if (rank == 5) ver = true; }), ), SwitchListTile(title: const Text("Verified"), value: ver, activeThumbColor: kOnsolGold, onChanged: (v) => setS(() => ver = v)), SwitchListTile(title: const Text("Exiled"), value: ban, activeThumbColor: Colors.red, onChanged: (v) => setS(() => ban = v)), const SizedBox(height: 10), // --- ENERGY REFILL BUTTON (2/2) --- ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.orangeAccent, foregroundColor: Colors.black, minimumSize: const Size(double.infinity, 40)), onPressed: () async { await user.reference.update({ 'energy': 2, 'lastEnergyRefill': FieldValue.serverTimestamp() }); if (ctx.mounted) Navigator.pop(ctx); }, child: const Text("REFILL ENERGY (2/2)", style: TextStyle(fontWeight: FontWeight.bold)) ), ], ), ), actions: [ TextButton(onPressed: () => Navigator.pop(ctx), child: const Text("CANCEL")), ElevatedButton( onPressed: () async { await user.reference.update({'rankLevel': rank, 'isVerified': ver, 'isBanned': ban}); if (ctx.mounted) Navigator.pop(ctx); }, child: const Text("APPLY"), ) ], ), ), ); } @override Widget build(BuildContext context) { return StreamBuilder( stream: FirebaseFirestore.instance.collection('users').snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) return const Center(child: CircularProgressIndicator()); return ListView( padding: const EdgeInsets.all(15), children: snapshot.data!.docs.map((u) { var d = u.data() as Map; int r = safeInt(d['rankLevel'] ?? 1); bool isBan = d['isBanned'] ?? false; return Card( color: Colors.grey[900], child: ListTile( leading: Icon(getRankIcon(r), color: isBan ? Colors.red : getRankColor(r)), title: Row(children: [ Text(d['username'] ?? 'Anonymous', style: TextStyle(color: isBan ? Colors.red : Colors.white)), verifiedBadge(d['isVerified'] ?? (r == 5)) ]), subtitle: Text(isBan ? "EXILED" : getRankName(r)), trailing: IconButton(icon: const Icon(Icons.shield, color: Colors.amber), onPressed: () => _showModeration(context, u)), ), ); }).toList(), ); }, ); } } // --- OTHER TABS --- class _ManageSeriesTab extends StatelessWidget { const _ManageSeriesTab(); void _add(BuildContext context) { final t = TextEditingController(); showDialog(context: context, builder: (ctx) => AlertDialog( backgroundColor: Colors.grey[900], title: const Text("New Series"), content: TextField(controller: t, decoration: const InputDecoration(hintText: "Series Title")), actions: [ElevatedButton(onPressed: () { FirebaseFirestore.instance.collection('manga').add({'title': t.text, 'reads': 0, 'readingMode': 'RL', 'author': 'Artist', 'coverUrl': ''}); Navigator.pop(ctx); }, child: const Text("ADD"))], )); } @override Widget build(BuildContext context) { return Scaffold(backgroundColor: Colors.transparent, floatingActionButton: FloatingActionButton(backgroundColor: Colors.white, child: const Icon(Icons.add, color: Colors.black), onPressed: () => _add(context)), body: StreamBuilder(stream: FirebaseFirestore.instance.collection('manga').snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) return const CircularProgressIndicator(); return ListView(padding: const EdgeInsets.all(15), children: snapshot.data!.docs.map((doc) => Card(color: Colors.grey[900], child: ListTile(title: Text(doc['title'] ?? 'Untitled'), trailing: IconButton(icon: const Icon(Icons.delete_outline, color: Colors.red), onPressed: () => doc.reference.delete())))).toList()); })); } } class _ManageMerchTab extends StatelessWidget { const _ManageMerchTab(); void _add(BuildContext context) { final n = TextEditingController(); final p = TextEditingController(); final u = TextEditingController(); String cat = 'vault'; showDialog(context: context, builder: (ctx) => StatefulBuilder(builder: (context, setS) => AlertDialog(backgroundColor: Colors.grey[900], title: const Text("New Item"), content: SingleChildScrollView(child: Column(mainAxisSize: MainAxisSize.min, children: [TextField(controller: n, decoration: const InputDecoration(hintText: "Name")), TextField(controller: p, decoration: const InputDecoration(hintText: "Price")), TextField(controller: u, decoration: const InputDecoration(hintText: "Buy URL")), DropdownButton(value: cat, isExpanded: true, dropdownColor: Colors.black, items: ['vault', 'prints', 'merch'].map((s) => DropdownMenuItem(value: s, child: Text(s.toUpperCase()))).toList(), onChanged: (v) => setS(() => cat = v!))])), actions: [ElevatedButton(onPressed: () { FirebaseFirestore.instance.collection('marketplace').add({'name': n.text, 'price': p.text, 'buyUrl': u.text, 'category': cat, 'imageUrl': ''}); Navigator.pop(ctx); }, child: const Text("ADD"))], ))); } @override Widget build(BuildContext context) { return Scaffold(backgroundColor: Colors.transparent, floatingActionButton: FloatingActionButton(backgroundColor: kOnsolGold, child: const Icon(Icons.add_shopping_cart, color: Colors.black), onPressed: () => _add(context)), body: StreamBuilder(stream: FirebaseFirestore.instance.collection('marketplace').snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) return const CircularProgressIndicator(); return ListView(padding: const EdgeInsets.all(15), children: snapshot.data!.docs.map((doc) => Card(color: Colors.grey[900], child: ListTile(title: Text(doc['name'] ?? 'Item'), subtitle: Text(doc['price'] ?? ''), trailing: IconButton(icon: const Icon(Icons.delete_outline, color: Colors.red), onPressed: () => doc.reference.delete())))).toList()); })); } } class _ManageInvitesTab extends StatelessWidget { const _ManageInvitesTab(); @override Widget build(BuildContext context) { return Column(children: [ const SizedBox(height: 20), ElevatedButton(style: ElevatedButton.styleFrom(backgroundColor: Colors.white, foregroundColor: Colors.black), onPressed: () { String code = List.generate(6, (i) => "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"[Random().nextInt(30)]).join(); FirebaseFirestore.instance.collection('invite_codes').doc(code).set({'isUsed': false, 'createdAt': FieldValue.serverTimestamp()}); }, child: const Text("GENERATE INVITE")), Expanded(child: StreamBuilder(stream: FirebaseFirestore.instance.collection('invite_codes').snapshots(), builder: (context, snapshot) { if (!snapshot.hasData) return const Center(child: CircularProgressIndicator()); var docs = snapshot.data!.docs; docs.sort((a,b) { var at = (a.data() as Map)['createdAt'] as Timestamp? ?? Timestamp.now(); var bt = (b.data() as Map)['createdAt'] as Timestamp? ?? Timestamp.now(); return bt.compareTo(at); }); return ListView(padding: const EdgeInsets.all(20), children: docs.map((doc) { var d = doc.data() as Map; return ListTile(title: Text(doc.id, style: const TextStyle(letterSpacing: 4, fontWeight: FontWeight.bold, color: Colors.white)), trailing: (d['isUsed'] ?? false) ? const Icon(Icons.check_circle, color: Colors.green) : const Icon(Icons.hourglass_empty, color: Colors.amber)); }).toList()); })) ]); } }