import 'dart:convert'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'package:socialbuddy_mobile/core/constants/colors.dart'; import 'package:socialbuddy_mobile/core/constants/api_constants.dart'; import '../../connect/screens/channels_screen.dart'; import '../../connect/screens/social_connect_details_screen.dart'; import '../../automation/screens/automation_screen.dart'; import '../../../core/constants/colors.dart'; class PostsScreen extends StatefulWidget { const PostsScreen({super.key}); @override State createState() => _PostsScreenState(); } class _PostsScreenState extends State { List _media = []; bool _isLoading = true; String? _error; String? _connectedChannelName; Map? _accountData; @override void initState() { super.initState(); _fetchMedia(); } Future _fetchMedia() async { if (!mounted) return; setState(() { _isLoading = true; _error = null; }); try { final prefs = await SharedPreferences.getInstance(); final userEmail = prefs.getString('user_email'); final connectedChannelId = prefs.getString('connectedChannel'); if (userEmail == null) { setState(() { _error = "User email not found. Please log in again."; _isLoading = false; }); return; } // Check if we have account details saved or fetch them if (connectedChannelId != null) { await _fetchAccountDetails(userEmail); } final url = Uri.parse('${ApiConstants.liveBaseUrl}/social/media?userId=$userEmail&limit=20'); final response = await http.get(url); if (!mounted) return; if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { _media = data['data'] ?? []; _isLoading = false; }); } else { final data = jsonDecode(response.body); setState(() { // Backend might return 'error' or 'message' _error = data['error'] ?? data['message'] ?? "Failed to load media"; _isLoading = false; }); } } catch (e) { if (mounted) { setState(() { _error = "An error occurred: $e"; _isLoading = false; }); } } } Future _fetchAccountDetails(String email) async { try { final response = await http.get( Uri.parse('${ApiConstants.liveBaseUrl}/social/account?userId=$email'), ); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { _accountData = data; _connectedChannelName = data['username']; }); } } catch (e) { debugPrint("Error fetching account for posts header: $e"); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.darkBg, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, title: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Media Library", style: GoogleFonts.nunito(fontWeight: FontWeight.bold)), if (_connectedChannelName != null) Text("Account: @$_connectedChannelName", style: GoogleFonts.nunito(fontSize: 12, color: Colors.white54)), ], ), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: _fetchMedia, ), ], ), body: RefreshIndicator( onRefresh: _fetchMedia, color: Colors.pinkAccent, child: _buildBody(), ), floatingActionButton: FloatingActionButton( onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Create Post feature coming soon!")), ); }, backgroundColor: Colors.blueAccent, child: const Icon(Icons.add, color: Colors.white), ), ); } Widget _buildBody() { if (_isLoading) { return const Center(child: CircularProgressIndicator(color: Colors.pinkAccent)); } if (_error != null) { return SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), child: Container( height: MediaQuery.of(context).size.height * 0.7, alignment: Alignment.center, padding: const EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 64, color: Colors.orangeAccent), const SizedBox(height: 16), Text( _error!, textAlign: TextAlign.center, style: const TextStyle(color: Colors.white70, fontSize: 16), ), const SizedBox(height: 24), if (_error!.contains("Connect a channel")) ElevatedButton( onPressed: () => Navigator.push( context, MaterialPageRoute(builder: (context) => const ChannelsScreen()), ).then((_) => _fetchMedia()), style: ElevatedButton.styleFrom(backgroundColor: Colors.pinkAccent), child: const Text("Go to Channels"), ) else ElevatedButton( onPressed: _fetchMedia, style: ElevatedButton.styleFrom(backgroundColor: Colors.blueAccent), child: const Text("Retry"), ), ], ), ), ); } if (_media.isEmpty) { return SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), child: Container( height: MediaQuery.of(context).size.height * 0.7, alignment: Alignment.center, padding: const EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.photo_library_outlined, size: 80, color: Colors.white10), const SizedBox(height: 24), Text( "No Instagram media found.", textAlign: TextAlign.center, style: GoogleFonts.nunito(fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), const Text( "Make sure you have an active Instagram business account connected.", textAlign: TextAlign.center, style: TextStyle(color: Colors.white38), ), const SizedBox(height: 32), ElevatedButton( onPressed: () => Navigator.push( context, MaterialPageRoute(builder: (context) => const ChannelsScreen()), ).then((_) => _fetchMedia()), style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: const Text("Connect Channel"), ), ], ), ), ); } return GridView.builder( padding: const EdgeInsets.all(16), physics: const AlwaysScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.65, crossAxisSpacing: 16, mainAxisSpacing: 16, ), itemCount: _media.length, itemBuilder: (context, index) { final item = _media[index]; final mediaType = item['media_type']; final mediaUrl = item['media_url']; final caption = item['caption'] ?? ""; final likes = item['like_count']?.toString() ?? "0"; final comments = item['comments_count']?.toString() ?? "0"; return Container( decoration: BoxDecoration( color: AppColors.cardBg, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.white.withOpacity(0.05)), boxShadow: [ BoxShadow(color: Colors.black26, blurRadius: 10, offset: const Offset(0, 5)), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Stack( children: [ ClipRRect( borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), child: Image.network( mediaUrl, fit: BoxFit.cover, width: double.infinity, height: double.infinity, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return Container( color: Colors.white.withOpacity(0.02), child: const Center(child: CircularProgressIndicator(strokeWidth: 2)), ); }, errorBuilder: (c, e, s) => Container( color: Colors.white10, child: const Center(child: Icon(Icons.broken_image, color: Colors.white24, size: 32)), ), ), ), Positioned( top: 8, right: 8, child: ClipRRect( borderRadius: BorderRadius.circular(8), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.black54.withOpacity(0.6), borderRadius: BorderRadius.circular(8), ), child: Text( _getMediaTypeName(mediaType), style: const TextStyle(color: Colors.white, fontSize: 8, fontWeight: FontWeight.bold), ), ), ), ), ), ], ), ), Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( caption, maxLines: 2, overflow: TextOverflow.ellipsis, style: GoogleFonts.nunito(fontSize: 12, color: Colors.white, height: 1.3), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _buildStatChip(Icons.favorite, likes, Colors.pinkAccent), _buildStatChip(Icons.comment, comments, Colors.blueAccent), ], ), ], ), ), ], ), ); }, ); } String _getMediaTypeName(String type) { switch (type) { case 'IMAGE': return 'PHOTO'; case 'VIDEO': return 'VIDEO'; case 'CAROUSEL_ALBUM': return 'CAROUSEL'; default: return type; } } Widget _buildStatChip(IconData icon, String value, Color color) { return Row( children: [ Icon(icon, size: 14, color: color), const SizedBox(width: 4), Text(value, style: const TextStyle(fontSize: 10, color: Colors.white70, fontWeight: FontWeight.bold)), ], ); } }