import 'dart:async';
import 'package:collection/collection.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_svg/svg.dart';
import 'package:geolocator/geolocator.dart';
import 'package:proxibuy/core/config/api_config.dart';
import 'package:proxibuy/core/config/app_colors.dart';
import 'package:proxibuy/core/gen/assets.gen.dart';
import 'package:proxibuy/data/models/offer_model.dart';
import 'package:proxibuy/presentation/notification_preferences/bloc/notification_preferences_bloc.dart';
import 'package:proxibuy/presentation/notification_preferences/bloc/notification_preferences_event.dart';
import 'package:proxibuy/presentation/offer/bloc/offer_bloc.dart';
import 'package:proxibuy/presentation/offer/bloc/offer_event.dart';
import 'package:proxibuy/presentation/offer/bloc/offer_state.dart';
import 'package:proxibuy/presentation/offer/bloc/widgets/category_offers_row.dart';
import 'package:proxibuy/presentation/pages/notification_preferences_page.dart';
import 'package:proxibuy/presentation/pages/reserved_list_page.dart';
import 'package:proxibuy/presentation/reservation/cubit/reservation_cubit.dart';
import 'package:proxibuy/presentation/widgets/gps_dialog.dart';
import 'package:proxibuy/presentation/widgets/notification_permission_dialog.dart';
import 'package:proxibuy/presentation/widgets/notification_panel.dart';
import 'package:proxibuy/services/mqtt_service.dart';
import 'package:shared_preferences/shared_preferences.dart';

class OffersPage extends StatefulWidget {
  final bool showDialogsOnLoad;

  const OffersPage({super.key, this.showDialogsOnLoad = false});

  @override
  State<OffersPage> createState() => _OffersPageState();
}

class _OffersPageState extends State<OffersPage> {
  List<String> _selectedCategories = [];
  StreamSubscription? _locationServiceSubscription;
  StreamSubscription? _mqttMessageSubscription;
  StreamSubscription? _connectivitySubscription;
  Timer? _locationTimer;
  bool _isSubscribedToOffers = false;
  bool _isGpsEnabled = false;
  bool _isConnectedToInternet = true;
  // Notifications panel state
  final GlobalKey _bellKey = GlobalKey();
  OverlayEntry? _notifOverlay;
  bool _notifVisible = false;
  int _notificationCount = 0;

  @override
  void initState() {
    super.initState();
    _checkInitialConnectivity();
    _initializePage();
    _initConnectivityListener();
    _fetchInitialReservations();
    _fetchNotificationCount();
  }

  @override
  void dispose() {
    _locationServiceSubscription?.cancel();
    _mqttMessageSubscription?.cancel();
    _locationTimer?.cancel();
    _connectivitySubscription?.cancel();
    _removeNotificationOverlay();
    super.dispose();
  }

  Future<void> _checkInitialConnectivity() async {
    final connectivityResult = await Connectivity().checkConnectivity();
    if (!mounted) return;
    setState(() {
      _isConnectedToInternet = !connectivityResult.contains(ConnectivityResult.none);
    });
  }

  Future<void> _initializePage() async {
    if (widget.showDialogsOnLoad) {
      WidgetsBinding.instance.addPostFrameCallback((_) async {
        if (mounted) {
          await showNotificationPermissionDialog(context);
          await showGPSDialog(context);
        }
      });
    }

    await _loadPreferences();
    _initLocationListener();
    _subscribeToUserOffersOnLoad();
  }

  void _initConnectivityListener() {
    _connectivitySubscription =
        Connectivity().onConnectivityChanged.listen((results) {
      final hasConnection = !results.contains(ConnectivityResult.none);
      if (mounted && _isConnectedToInternet != hasConnection) {
        setState(() {
          _isConnectedToInternet = hasConnection;
        });

        if (hasConnection) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text('اتصال به اینترنت برقرار شد.'),
              backgroundColor: Colors.green,
            ),
          );
        } else {
          context.read<OffersBloc>().add(ClearOffers());
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
              content: Text('اتصال به اینترنت قطع شد.'),
              backgroundColor: Colors.red,
            ),
          );
        }
      }
    });
  }

  Future<void> _fetchInitialReservations() async {
    if (!_isConnectedToInternet) return;
    try {
      const storage = FlutterSecureStorage();
      final token = await storage.read(key: 'accessToken');
      if (token == null) return;

      final dio = Dio();
      final response = await dio.get(
        ApiConfig.baseUrl + ApiConfig.getReservations,
        options: Options(headers: {'Authorization': 'Bearer $token'}),
      );

      if (response.statusCode == 200 && mounted) {
        final List<dynamic> reserves = response.data['reserves'];
        final List<String> reservedIds = reserves
            .map((reserveData) =>
                (reserveData['Discount']['ID'] as String?) ?? '')
            .where((id) => id.isNotEmpty)
            .toList();

        context.read<ReservationCubit>().setReservedIds(reservedIds);
      }
    } catch (e) {
      debugPrint("Error fetching initial reservations: $e");
    }
  }

  Future<void> _subscribeToUserOffersOnLoad() async {
    final storage = const FlutterSecureStorage();
    final userID = await storage.read(key: 'userID');
    if (userID != null && mounted) {
      _subscribeToUserOffers(userID);
    }
  }

  void _initLocationListener() {
    _checkInitialGpsStatus();
    _locationServiceSubscription =
        Geolocator.getServiceStatusStream().listen((status) {
      final isEnabled = status == ServiceStatus.enabled;
      if (mounted && _isGpsEnabled != isEnabled) {
        setState(() {
          _isGpsEnabled = isEnabled;
        });
        if (isEnabled) {
          _startSendingLocationUpdates();
        } else {
          debugPrint("❌ Location Service Disabled. Stopping updates.");
          _locationTimer?.cancel();
          context.read<OffersBloc>().add(ClearOffers());
        }
      }
    });
  }

  Future<void> _checkInitialGpsStatus() async {
    final status = await Geolocator.isLocationServiceEnabled();
    if (mounted) {
      setState(() {
        _isGpsEnabled = status;
      });
      if (_isGpsEnabled) {
        _startSendingLocationUpdates();
      }
    }
  }

  void _startSendingLocationUpdates() {
    debugPrint("🚀 Starting periodic location updates.");
    _locationTimer?.cancel();
    _locationTimer = Timer.periodic(const Duration(seconds: 30), (timer) {
      _sendLocationUpdate();
    });
    _sendLocationUpdate();
  }

  Future<void> _sendLocationUpdate() async {
    if (!_isConnectedToInternet || !_isGpsEnabled) return;

    final mqttService = context.read<MqttService>();
    if (!mqttService.isConnected) {
      debugPrint("⚠️ MQTT not connected in OffersPage. Cannot send location.");
      return;
    }

    try {
      LocationPermission permission = await Geolocator.checkPermission();
      if (permission == LocationPermission.denied) {
        permission = await Geolocator.requestPermission();
      }

      if (permission == LocationPermission.denied ||
          permission == LocationPermission.deniedForever) {
        debugPrint("🚫 Location permission denied by user.");
        return;
      }

      final position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high,
      );

      const storage = FlutterSecureStorage();
      final userID = await storage.read(key: 'userID');

      if (userID == null) {
        debugPrint("⚠️ UserID not found. Cannot send location.");
        return;
      }

      final payload = {
        "userID": userID,
        "lat": position.latitude,
        "lng": position.longitude
      };

      mqttService.publish("proxybuy/sendGps", payload);
    } catch (e) {
      debugPrint("❌ Error sending location update in OffersPage: $e");
    }
  }

  void _subscribeToUserOffers(String userID) {
    if (_isSubscribedToOffers) return;

    final mqttService = context.read<MqttService>();
    if (!mqttService.isConnected) {
        debugPrint("⚠️ Cannot subscribe. MQTT client is not connected.");
        return;
    }

    final topic = 'user-proxybuy/$userID';
    mqttService.subscribe(topic);
    _isSubscribedToOffers = true;

    _mqttMessageSubscription = mqttService.messages.listen((message) {
      final data = message['data'];

      if (data == null || data is! List) {
        if (mounted) {
          context.read<OffersBloc>().add(const OffersReceivedFromMqtt([]));
        }
        return;
      }

      try {
        List<OfferModel> offers = data
            .whereType<Map<String, dynamic>>()
            .map((json) => OfferModel.fromJson(json))
            .toList();

        if (mounted) {
          context.read<OffersBloc>().add(OffersReceivedFromMqtt(offers));
        }
      } catch (e, stackTrace) {
        debugPrint("❌ Error parsing offers from MQTT: $e");
        debugPrint(stackTrace.toString());
      }
    });
  }

  Future<void> _loadPreferences() async {
    final prefs = await SharedPreferences.getInstance();
    final savedCategories =
        prefs.getStringList('user_selected_categories') ?? [];

    if (mounted) {
      setState(() {
        _selectedCategories = savedCategories;
      });
    }
  }

  Future<void> _fetchNotificationCount() async {
    try {
      const storage = FlutterSecureStorage();
      final token = await storage.read(key: 'accessToken');
      if (token == null) {
        if (mounted) setState(() => _notificationCount = 0);
        return;
      }
      final dio = Dio();
      final response = await dio.get(
        'https://proxybuy.liara.run/notify/get',
        options: Options(headers: {'Authorization': 'Bearer $token'}),
      );
      if (!mounted) return;
      if (response.statusCode == 200) {
        final List<dynamic> data = response.data['data'] ?? [];
        // Filter only active notifications (Status: true)
        final activeNotifications = data.where((item) => item['Status'] == true).toList();
        setState(() => _notificationCount = activeNotifications.length);
      } else {
        setState(() => _notificationCount = 0);
      }
    } catch (_) {
      if (mounted) setState(() => _notificationCount = 0);
    }
  }

  void _showNotificationOverlay() {
    if (_notifOverlay != null) return;

    final overlay = Overlay.of(context);
    final renderBox = _bellKey.currentContext?.findRenderObject() as RenderBox?;
    if (renderBox == null) return;

    final bellSize = renderBox.size;
    final bellPosition = renderBox.localToGlobal(Offset.zero);

    final screenSize = MediaQuery.of(context).size;
    final panelWidth = screenSize.width.clamp(0, 360);
    final width = (panelWidth > 320 ? 320.0 : panelWidth - 24).toDouble();
    final top = bellPosition.dy + bellSize.height; // stick to icon
    final tentativeLeft = bellPosition.dx + bellSize.width - width;
    final double left = tentativeLeft.clamp(8.0, screenSize.width - width - 8.0).toDouble();

    _notifOverlay = OverlayEntry(
      builder: (ctx) {
        return Stack(
          children: [
            // Tap outside to close
            Positioned.fill(
              child: GestureDetector(
                onTap: _hideNotificationOverlay,
                behavior: HitTestBehavior.opaque,
                child: const SizedBox.shrink(),
              ),
            ),
            Positioned(
              top: top,
              left: left,
              child: TweenAnimationBuilder<double>(
                tween: Tween(begin: 0.9, end: 1.0),
                duration: const Duration(milliseconds: 180),
                curve: Curves.easeOutBack,
                builder: (context, scale, child) {
                  // Ensure scale is valid
                  final validScale = scale.clamp(0.0, 1.0);
                  return Opacity(
                    opacity: validScale,
                    child: Transform.scale(
                      scale: validScale,
                      alignment: Alignment.topLeft,
                      child: Material(
                        color: Colors.transparent,
                        child: Container(
                          width: width,
                          constraints: const BoxConstraints(
                            maxHeight: 250,
                            minWidth: 370,
                          ),
                          decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.circular(16),
                            boxShadow: [
                              BoxShadow(
                                color: Colors.black.withOpacity(0.08),
                                blurRadius: 24,
                                spreadRadius: 4,
                                offset: const Offset(0, 8),
                              ),
                            ],
                          ),
                          child: Directionality(
                            textDirection: TextDirection.rtl,
                            child: NotificationPanel(
                              onClose: _hideNotificationOverlay,
                              onListChanged: () {
                                _fetchNotificationCount();
                              },
                            ),
                          ),
                        ),
                      ),
                    ),
                  );
                },
              ),
            ),
          ],
        );
      },
    );

    overlay.insert(_notifOverlay!);
    setState(() => _notifVisible = true);
  }

  void _hideNotificationOverlay() {
    _notifOverlay?.remove();
    _notifOverlay = null;
    if (mounted) setState(() => _notifVisible = false);
  }

  void _removeNotificationOverlay() {
    _notifOverlay?.remove();
    _notifOverlay = null;
  }

  Future<void> _onRefresh() async {
    await _sendLocationUpdate();
    await _fetchNotificationCount();
    await Future.delayed(const Duration(milliseconds: 300));
  }

  Widget _buildFavoriteCategoriesSection() {
    return Padding(
      padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Text(
                'دسته‌بندی‌های مورد علاقه شما',
                style: TextStyle(fontSize: 19, fontWeight: FontWeight.bold),
              ),
              TextButton(
                onPressed: () async {
                  await Navigator.of(context).push<bool>(
                    MaterialPageRoute(
                      builder: (context) => const NotificationPreferencesPage(
                        loadFavoritesOnStart: true,
                      ),
                    ),
                  );

                  if (!mounted) return;

                  context
                      .read<NotificationPreferencesBloc>()
                      .add(ResetSubmissionStatus());

                  _loadPreferences();
                },
                child: Row(
                  children: [
                    SvgPicture.asset(Assets.icons.edit.path),
                    const SizedBox(width: 4),
                    const Text(
                      'ویرایش',
                      style: TextStyle(color: AppColors.active),
                    ),
                  ],
                ),
              ),
            ],
          ),
          const Divider(height: 1),
          const SizedBox(height: 12),
          if (_selectedCategories.isEmpty)
            const Padding(
              padding: EdgeInsets.only(bottom: 8.0),
              child: Text(
                'شما هنوز دسته‌بندی مورد علاقه خود را انتخاب نکرده‌اید.',
                style: TextStyle(color: Colors.grey),
              ),
            )
          else
            Wrap(
              spacing: 8.0,
              runSpacing: 8.0,
              children: _selectedCategories.map((category) {
                return Container(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 12.0,
                    vertical: 6.0,
                  ),
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.grey.shade300),
                    borderRadius: BorderRadius.circular(20.0),
                  ),
                  child: Text(category),
                );
              }).toList(),
            ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.white,
          automaticallyImplyLeading: false,
          title: Padding(
            padding: const EdgeInsets.symmetric(
              horizontal: 15.0,
              vertical: 0.0,
            ),
            child: Assets.icons.logoWithName.svg(height: 40, width: 200),
          ),
          actions: [
            // Notification bell with badge and overlay trigger
            Stack(
              clipBehavior: Clip.none,
              alignment: Alignment.center,
              children: [
                IconButton(
                  key: _bellKey,
                  onPressed: () {
                    if (_notifVisible) {
                      _hideNotificationOverlay();
                    } else {
                      _fetchNotificationCount();
                      _showNotificationOverlay();
                    }
                  },
                  icon: Assets.icons.notification.svg(),
                ),
                if (_notificationCount > 0)
                  Positioned(
                    top: 3,
                    // in RTL, actions are on the left; badge at top-left of icon
                    right: 7,
                    child: Container(
                      padding: const EdgeInsets.all(4),
                      decoration: BoxDecoration(
                        color: Colors.red,
                        shape: BoxShape.circle,
                        border: Border.all(color: Colors.white, width: 1.5),
                      ),
                      constraints: const BoxConstraints(minWidth: 18, minHeight: 18),
                      child: Center(
                        child: Text(
                          '$_notificationCount',
                          style: const TextStyle(
                            color: Colors.white,
                            fontSize: 11,
                            fontWeight: FontWeight.bold,
                          ),
                          textAlign: TextAlign.center,
                        ),
                      ),
                    ),
                  ),
              ],
            ),
            BlocBuilder<ReservationCubit, ReservationState>(
              builder: (context, state) {
                final reservedCount = state.reservedProductIds.length;
                return Stack(
                  alignment: Alignment.center,
                  children: [
                    IconButton(
                      onPressed: () {
                        Navigator.of(context).push(
                          MaterialPageRoute(
                            builder: (_) => const ReservedListPage(),
                          ),
                        );
                      },
                      icon: Assets.icons.scanBarcode.svg(),
                    ),
                    if (reservedCount > 0)
                      Positioned(
                        top: 0,
                        right: 2,
                        child: GestureDetector(
                          onTap: () {
                            Navigator.of(context).push(
                              MaterialPageRoute(
                                builder: (_) => const ReservedListPage(),
                              ),
                            );
                          },
                          child: Container(
                            padding: const EdgeInsets.all(4),
                            decoration: BoxDecoration(
                              color: Colors.green,
                              shape: BoxShape.circle,
                              border:
                                  Border.all(color: Colors.white, width: 1.5),
                            ),
                            constraints: const BoxConstraints(
                              minWidth: 18,
                              minHeight: 18,
                            ),
                            child: Padding(
                              padding: const EdgeInsets.fromLTRB(2, 4, 2, 2),
                              child: Text(
                                '$reservedCount',
                                style: const TextStyle(
                                  color: Colors.white,
                                  fontSize: 11,
                                  fontWeight: FontWeight.bold,
                                ),
                                textAlign: TextAlign.center,
                              ),
                            ),
                          ),
                        ),
                      ),
                  ],
                );
              },
            ),
            const SizedBox(width: 8),
          ],
        ),
        body: RefreshIndicator(
          onRefresh: _onRefresh,
          color: AppColors.active,
          child: SingleChildScrollView(
            physics: const AlwaysScrollableScrollPhysics(),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                _buildFavoriteCategoriesSection(),
                OffersView(
                  isGpsEnabled: _isGpsEnabled,
                  isConnectedToInternet: _isConnectedToInternet,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class OffersView extends StatelessWidget {
  final bool isGpsEnabled;
  final bool isConnectedToInternet;

  const OffersView({
    super.key,
    required this.isGpsEnabled,
    required this.isConnectedToInternet,
  });

  @override
  Widget build(BuildContext context) {
    if (!isConnectedToInternet) {
      return _buildNoInternetUI(context);
    }

    if (!isGpsEnabled) {
      return _buildGpsActivationUI(context);
    }

    return BlocBuilder<OffersBloc, OffersState>(
      builder: (context, state) {
        if (state is OffersInitial) {
          return const SizedBox(
            height: 300,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  CircularProgressIndicator(),
                  SizedBox(height: 20),
                  Text("در حال یافتن بهترین پیشنهادها برای شما..."),
                ],
              ),
            ),
          );
        }

        if (state is OffersLoadSuccess) {
          if (state.offers.isEmpty) {
            return const SizedBox(
              height: 300,
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text("فعلاً تخفیفی در این اطراف نیست!"),
                    Text("کمی قدم بزنید..."),
                  ],
                ),
              ),
            );
          }

          final groupedOffers = groupBy(
            state.offers,
            (OfferModel offer) => offer.category,
          );
          final categories = groupedOffers.keys.toList();

          return ListView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            padding: const EdgeInsets.only(top: 16),
            itemCount: categories.length,
            itemBuilder: (context, index) {
              final category = categories[index];
              final offersForCategory = groupedOffers[category]!;

              return CategoryOffersRow(
                categoryTitle: category,
                offers: offersForCategory,
              ).animate().fade(duration: 500.ms).slideY(
                  begin: 0.3, duration: 400.ms, curve: Curves.easeOut);
            },
          );
        }

        if (state is OffersLoadFailure) {
          return SizedBox(
            height: 200,
            child: Center(child: Text("خطا در بارگذاری: ${state.error}")),
          );
        }

        return const SizedBox.shrink();
      },
    );
  }

  Widget _buildGpsActivationUI(BuildContext context) {
    return Center(
      child: SizedBox(
        child: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              const SizedBox(height: 85),
              SvgPicture.asset(Assets.images.emptyHome.path),
              const SizedBox(height: 60),
              ElevatedButton(
                onPressed: () async {
                  await Geolocator.openLocationSettings();
                },
                style: ElevatedButton.styleFrom(
                  backgroundColor: AppColors.confirm,
                  foregroundColor: Colors.white,
                  disabledBackgroundColor: Colors.grey,
                  padding: const EdgeInsets.symmetric(
                    vertical: 12,
                    horizontal: 125,
                  ),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(50),
                  ),
                ),
                child: const Text(
                  'فعال‌سازی GPS',
                  style: TextStyle(
                    fontFamily: 'Dana',
                    fontSize: 16,
                    fontWeight: FontWeight.normal,
                  ),
                ),
              ),
              const SizedBox(height: 15),
              const Text('جست‌وجوی تصادفی'),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildNoInternetUI(BuildContext context) {
    return SizedBox(
      height: 300,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.wifi_off_rounded, size: 80, color: Colors.grey[400]),
            const SizedBox(height: 20),
            const Text(
              "اتصال به اینترنت برقرار نیست",
              style: TextStyle(fontSize: 18, color: Colors.grey),
            ),
            const SizedBox(height: 10),
            const Text(
              "لطفاً اتصال خود را بررسی کرده و دوباره تلاش کنید.",
              style: TextStyle(color: Colors.grey),
            ),
          ],
        ),
      ),
    );
  }
}