import 'dart:async';

import 'package:flutter/material.dart';
import 'package:frontend_eccp_mobile/app/core/constants/constants.dart';
import 'package:frontend_eccp_mobile/app/core/navigation/app_resume_once.dart';
import 'package:frontend_eccp_mobile/app/core/navigation/settings_navigator.dart';
import 'package:frontend_eccp_mobile/app/core/services/location_permission_service.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';

typedef BottomSheetBuilder = Widget Function(BuildContext context);

typedef LocationSheetBuilder =
    Widget Function(
      BuildContext context, {
      required VoidCallback onOpenSettings,
      VoidCallback? onRequestNow,
    });

class BottomSheetService {
  BottomSheetService._();

  static bool _isShown = false;

  static BottomSheetBuilder? _noInternetBuilder;
  static BottomSheetBuilder? _serverErrorBuilder;
  static BottomSheetBuilder? _notFoundBuilder;
  static BottomSheetBuilder? _sessionExpiredBuilder;
  static LocationSheetBuilder? _locationPermissionBuilder;

  static StreamSubscription<InternetConnectionStatus>? _connSub;

  static void configure({
    BottomSheetBuilder? noInternetBuilder,
    BottomSheetBuilder? serverErrorBuilder,
    BottomSheetBuilder? notFoundBuilder,
    BottomSheetBuilder? sessionExpiredBuilder,
    LocationSheetBuilder? locationPermissionBuilder,
  }) {
    _noInternetBuilder = noInternetBuilder;
    _serverErrorBuilder = serverErrorBuilder;
    _notFoundBuilder = notFoundBuilder;
    _sessionExpiredBuilder = sessionExpiredBuilder;
    _locationPermissionBuilder = locationPermissionBuilder;
  }

  static Future<void> showNoInternet() => _show(
    _noInternetBuilder,
    _defaultNoInternet,
    autoDismissOnReconnect: true,
  );

  static Future<void> showServerError() =>
      _show(_serverErrorBuilder, _defaultServerError);

  static Future<void> showNotFound() =>
      _show(_notFoundBuilder, _defaultNotFound);

  static Future<void> showSessionExpired() => _show(
    _sessionExpiredBuilder,
    _defaultSessionExpired,
    isDismissible: false,
  );

  static Future<void> showCustom(
    BottomSheetBuilder builder, {
    bool isDismissible = true,
  }) {
    return _show(builder, builder, isDismissible: isDismissible);
  }

  static Future<T?> showCustomReturn<T>(
    Widget Function(BuildContext) builder, {
    bool isDismissible = true,
  }) async {
    return showModalBottomSheet<T>(
      context: navigatorKey.currentContext!,
      isDismissible: isDismissible,
      isScrollControlled: true,

      backgroundColor: Colors.transparent,
      enableDrag: isDismissible,
      useRootNavigator: true,
      builder: builder,
    );
  }

  static Future<void> showLocationPermission({
    required VoidCallback onOpenSettings,
    VoidCallback? onRequestNow,
  }) {
    final custom = _locationPermissionBuilder == null
        ? null
        : (BuildContext ctx) => _locationPermissionBuilder!(
            ctx,
            onOpenSettings: onOpenSettings,
            onRequestNow: onRequestNow,
          );

    return _show(
      custom,
      (ctx) => _defaultLocationPermission(
        ctx,
        onOpenSettings: onOpenSettings,
        onRequestNow: onRequestNow,
      ),
    );
  }

  static Future<void> _show(
    BottomSheetBuilder? custom,
    BottomSheetBuilder fallback, {
    bool autoDismissOnReconnect = false,
    bool isDismissible = true,
  }) async {
    final navState = navigatorKey.currentState;
    final overlayContext = navState?.overlay?.context ?? navState?.context;

    if (overlayContext == null || _isShown) return;

    _isShown = true;

    if (autoDismissOnReconnect) {
      await _connSub?.cancel();
      _connSub = InternetConnectionChecker.instance.onStatusChange.listen(
        (status) {
          if (status == InternetConnectionStatus.connected && _isShown) {
            final navigator = navigatorKey.currentState;
            if (navigator != null && navigator.canPop()) {
              navigator.pop();
            }
          }
        },
      );
    }

    try {
      if (!overlayContext.mounted) return;

      await showMaterialModalBottomSheet<void>(
        context: overlayContext,
        backgroundColor: Colors.transparent,
        isDismissible: isDismissible,
        enableDrag: isDismissible,
        useRootNavigator: true,
        duration: AppDurations.modalTransition,
        builder: (ctx) {
          return WillPopScope(
            onWillPop: () async => isDismissible,
            child: SafeArea(
              top: false,
              bottom: false,
              child: custom != null ? custom(ctx) : fallback(ctx),
            ),
          );
        },
      );
    } finally {
      _isShown = false;
      await _connSub?.cancel();
      _connSub = null;
    }
  }

  static Widget _defaultNoInternet(BuildContext context) => Padding(
    padding: AppPadding.p24,
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const Icon(Icons.wifi_off, size: AppIconSizes.xxl),
        AppSpacing.h12,
        Text('Tidak ada internet', style: AppTextStyles.h3),
        AppSpacing.h8,
        Text(
          'Periksa koneksi kamu lalu coba lagi.',
          style: AppTextStyles.small,
          textAlign: TextAlign.center,
        ),
      ],
    ),
  );

  static Widget _defaultServerError(BuildContext context) => Padding(
    padding: AppPadding.p24,
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const Icon(Icons.cloud_off, size: AppIconSizes.xxl),
        AppSpacing.h12,
        Text('Gangguan server', style: AppTextStyles.h3),
        AppSpacing.h8,
        Text(
          'Coba beberapa saat lagi.',
          style: AppTextStyles.small,
          textAlign: TextAlign.center,
        ),
      ],
    ),
  );

  static Widget _defaultNotFound(BuildContext context) => Padding(
    padding: AppPadding.p24,
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const Icon(Icons.cloud_off, size: AppIconSizes.xxl),
        AppSpacing.h12,
        Text('Opps, kamu tersesat', style: AppTextStyles.h3),
        AppSpacing.h8,
        Text(
          'Baik, dimengerti. Mari kembali ke jalur semula.',
          style: AppTextStyles.small,
          textAlign: TextAlign.center,
        ),
      ],
    ),
  );

  static Widget _defaultSessionExpired(BuildContext context) => Padding(
    padding: AppPadding.p24,
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const Icon(Icons.lock_outline, size: AppIconSizes.xxl),
        AppSpacing.h12,
        Text('Sesi berakhir', style: AppTextStyles.h3),
        AppSpacing.h8,
        Text(
          'Silakan login ulang untuk melanjutkan.',
          style: AppTextStyles.small,
          textAlign: TextAlign.center,
        ),
        AppSpacing.h16,
        SizedBox(
          width: double.infinity,
          child: ElevatedButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('Login Ulang', style: AppTextStyles.button),
          ),
        ),
      ],
    ),
  );

  static Widget _defaultLocationPermission(
    BuildContext context, {
    required VoidCallback onOpenSettings,
    VoidCallback? onRequestNow,
  }) {
    return Padding(
      padding: AppPadding.p24,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Icon(Icons.my_location, size: AppIconSizes.xxl),
          AppSpacing.h12,
          Text('Permintaan Akses Lokasi', style: AppTextStyles.h3),
          AppSpacing.h8,
          Text(
            'Aplikasi ingin meminta akses lokasi kamu agar dapat memberikan pengalaman terbaik. Kamu dapat mengizinkan akses lokasi melalui pengaturan atau langsung sekarang.',
            style: AppTextStyles.small,
            textAlign: TextAlign.center,
          ),
          AppSpacing.h16,
          SizedBox(
            width: double.infinity,
            child: ElevatedButton(
              onPressed: () async {
                final resumeFut = waitRecheckOnNextResume(() async {
                  if (await LocationPermissionService.recheckGranted()) {
                    onOpenSettings();
                  }
                });

                await SettingsNavigator.openAppSettings();
                await resumeFut;
              },
              child: Text('Buka Pengaturan', style: AppTextStyles.button),
            ),
          ),
          if (onRequestNow != null) ...[
            AppSpacing.h8,
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
                onRequestNow();
              },
              child: Text('Izinkan Sekarang', style: AppTextStyles.label),
            ),
          ],
        ],
      ),
    );
  }
}
