import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../../push/push_registration.dart';
import '../../../../push/push_status.dart';
import '../../../../routing/app_routes.dart';
import '../../../../state/app/modules/capabilities/bloc/capabilities_cubit.dart';
import '../../../../state/app/modules/settings/bloc/settings_cubit.dart';
import '../../../../widget/centered_leading.dart';
import '../widgets/push_status_sheet.dart';
import '../widgets/settings_checkbox_tile.dart';

class TalkSection extends StatelessWidget {
  const TalkSection({super.key});

  @override
  Widget build(BuildContext context) {
    final settings = context.watch<SettingsCubit>();
    final talkSettings = settings.val().talkSettings;
    return Column(
      children: [
        SettingsCheckboxTile(
          icon: Icons.star_border,
          title: 'Favoriten im Talk nach oben sortieren',
          value: talkSettings.sortFavoritesToTop,
          onChanged: (e) =>
              settings.val(write: true).talkSettings.sortFavoritesToTop = e,
        ),
        SettingsCheckboxTile(
          icon: Icons.mark_email_unread_outlined,
          title: 'Ungelesene Chats nach oben sortieren',
          value: talkSettings.sortUnreadToTop,
          onChanged: (e) =>
              settings.val(write: true).talkSettings.sortUnreadToTop = e,
        ),
        ListTile(
          leading: const Icon(Icons.wallpaper_outlined),
          title: const Text('Chat-Hintergrund'),
          subtitle: const Text('Bild, Farbe und Darstellung anpassen'),
          trailing: const Icon(Icons.arrow_right),
          onTap: () => AppRoutes.openChatBackgroundSettings(context),
        ),
        _PushSettings(
          settings: settings,
          capabilities: context.read<CapabilitiesCubit>(),
          enabled: settings.val().notificationSettings.enabled,
          devMode: settings.val().devToolsEnabled,
        ),
      ],
    );
  }
}

/// The push area: the enable switch carries an at-a-glance health icon (green
/// check / red X) right before the checkbox, and the detailed status checklist
/// is hidden — it only surfaces when the chain is broken or the developer mode
/// is on. Owns the [PushStatusReport] loading so the inline icon and the detail
/// entry share one source of truth.
class _PushSettings extends StatefulWidget {
  final SettingsCubit settings;
  final CapabilitiesCubit capabilities;
  final bool enabled;
  final bool devMode;

  const _PushSettings({
    required this.settings,
    required this.capabilities,
    required this.enabled,
    required this.devMode,
  });

  @override
  State<_PushSettings> createState() => _PushSettingsState();
}

class _PushSettingsState extends State<_PushSettings>
    with WidgetsBindingObserver {
  PushStatusReport? _report;

  /// True while a (de)registration triggered by the switch is in flight. The
  /// report collected in that window still reflects the pre-registration state,
  /// so the status is shown as "loading" instead of briefly flashing red.
  bool _busy = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    unawaited(_load());
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant _PushSettings oldWidget) {
    super.didUpdateWidget(oldWidget);
    // Toggling the setting changes several links at once — re-collect.
    if (oldWidget.enabled != widget.enabled) unawaited(_load());
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    // The OS permission can change while the app is backgrounded.
    if (state == AppLifecycleState.resumed) unawaited(_load());
  }

  Future<void> _load() async {
    final caps = widget.capabilities.state;
    final report = await collectPushStatus(
      settingEnabled: widget.settings.val().notificationSettings.enabled,
      capabilityPush: caps.pushNotifications,
      capabilitiesLoaded: caps.loaded,
    );
    if (!mounted) return;
    setState(() => _report = report);
  }

  void _onToggle(bool enabled) {
    widget.settings.val(write: true).notificationSettings.enabled = enabled;
    // Turning off does NOT unregister: the device stays subscribed so silent
    // sync pushes keep arriving; the message handler and iOS NSE suppress only
    // the visible notification (via the mirrored flag). Enabling (re-)registers
    // and ensures the OS permission.
    if (!enabled) return;
    setState(() => _busy = true);
    final messenger = ScaffoldMessenger.of(context);
    unawaited(() async {
      try {
        // Only register when the OS permission isn't explicitly denied —
        // otherwise NC + proxy would push into the void.
        if (await PushRegistration.requestOsPermission()) {
          await PushRegistration().register();
        } else {
          messenger.showSnackBar(
            const SnackBar(
              content: Text(
                'Die Benachrichtigungsberechtigung wurde in den '
                'Systemeinstellungen deaktiviert. Bitte aktiviere sie dort, um '
                'Push-Benachrichtigungen zu erhalten.',
              ),
            ),
          );
        }
      } finally {
        if (mounted) await _load();
        if (mounted) setState(() => _busy = false);
      }
    }());
  }

  @override
  Widget build(BuildContext context) {
    final report = _report;
    final broken =
        widget.enabled && !_busy && report != null && !report.chainHealthy;
    return Column(
      children: [
        SettingsCheckboxTile(
          icon: Icons.notifications_active_outlined,
          title: 'Push-Benachrichtigungen',
          subtitle: 'Benachrichtigungen bei neuen Talk-Nachrichten erhalten',
          value: widget.enabled,
          beforeCheckbox: _inlineStatusIcon(report),
          onChanged: _onToggle,
        ),
        // Detail entry only when there is a problem to fix or for developers.
        if (broken || widget.devMode) _detailTile(error: broken),
      ],
    );
  }

  /// Health icon shown before the checkbox — a spinner while a registration is
  /// in flight, otherwise the green/red verdict once the report has loaded.
  Widget? _inlineStatusIcon(PushStatusReport? report) {
    if (_busy) {
      return const SizedBox(
        width: 18,
        height: 18,
        child: CircularProgressIndicator(strokeWidth: 2),
      );
    }
    if (!widget.enabled || report == null) return null;
    final healthy = report.chainHealthy;
    return Icon(
      healthy ? Icons.check_circle : Icons.cancel,
      color: healthy ? Colors.green : Theme.of(context).colorScheme.error,
      semanticLabel: healthy ? 'Push in Ordnung' : 'Push funktioniert nicht',
    );
  }

  /// The full status checklist entry — same list-tile footprint whether broken
  /// or not; a problem is signalled only through the error-colored icon/text.
  Widget _detailTile({required bool error}) {
    final color = error ? Theme.of(context).colorScheme.error : null;
    final textStyle = color == null ? null : TextStyle(color: color);
    return ListTile(
      leading: CenteredLeading(
        Icon(Icons.monitor_heart_outlined, color: color),
      ),
      title: Text('Push-Status', style: textStyle),
      subtitle: Text(
        error
            ? 'Ein Schritt in der Zustellkette ist unterbrochen'
            : 'Registrierung und Zustellung im Detail',
        style: textStyle,
      ),
      trailing: Icon(Icons.arrow_right, color: color),
      // The sheet can re-register; re-collect on close so the dot reflects it.
      onTap: () async {
        await showPushStatusSheet(context);
        if (mounted) await _load();
      },
    );
  }
}
