import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
import 'package:url_launcher/url_launcher_string.dart';

import '../../api/emergency/emergency_notice.dart';
import '../../api/emergency/emergency_notice_client.dart';
import '../../state/app/modules/settings/bloc/settings_cubit.dart';

/// Wraps the app and surfaces a backend-independent emergency notice on cold
/// start and resume. Renders [child] unchanged and only overlays a dialog when
/// the foreign source has an active message. Independent of MarianumConnect and
/// the login state by design — the fallback for when the backend is gone.
class EmergencyNoticeGate extends StatefulWidget {
  final Widget child;

  const EmergencyNoticeGate({required this.child, super.key});

  @override
  State<EmergencyNoticeGate> createState() => _EmergencyNoticeGateState();
}

class _EmergencyNoticeGateState extends State<EmergencyNoticeGate>
    with WidgetsBindingObserver {
  final EmergencyNoticeClient _client = EmergencyNoticeClient();
  bool _showing = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    WidgetsBinding.instance.addPostFrameCallback((_) => unawaited(_check()));
  }

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

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) unawaited(_check());
  }

  Future<void> _check() async {
    if (_showing || !mounted) return;
    final url = context
        .read<SettingsCubit>()
        .val()
        .devToolsSettings
        .resolveEmergencyNoticeUrl();
    if (url == null) return;

    final notice = await _client.fetch(url);
    if (notice == null || !mounted || _showing) return;

    _showing = true;
    try {
      await showDialog<void>(
        context: context,
        barrierDismissible: notice.dismissible,
        builder: (_) => _EmergencyNoticeDialog(notice: notice),
      );
    } finally {
      _showing = false;
    }
  }

  @override
  Widget build(BuildContext context) => widget.child;
}

class _EmergencyNoticeDialog extends StatelessWidget {
  final EmergencyNotice notice;

  const _EmergencyNoticeDialog({required this.notice});

  Future<void> _openLink(String? href) async {
    if (href == null) return;
    if (await canLaunchUrlString(href)) {
      await launchUrlString(href);
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final body = MarkdownBody(
      data: notice.body,
      onTapLink: (_, href, _) => unawaited(_openLink(href)),
    );

    if (notice.dismissible) {
      return AlertDialog(
        title: notice.title == null ? null : Text(notice.title!),
        content: SingleChildScrollView(child: body),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('Schließen'),
          ),
        ],
      );
    }

    // Full-screen, non-dismissible: no close affordance, back is blocked.
    return PopScope(
      canPop: false,
      child: Dialog.fullscreen(
        child: SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(24),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                if (notice.title != null) ...[
                  Text(
                    notice.title!,
                    style: theme.textTheme.headlineSmall?.copyWith(
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                  const SizedBox(height: 16),
                ],
                Expanded(
                  child: SingleChildScrollView(
                    physics: const AlwaysScrollableScrollPhysics(),
                    child: body,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
