import 'dart:async';

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

import '../../../../../widget/info_dialog.dart';
import '../bloc/loadable_state_bloc.dart';

class LoadableStateErrorBar extends StatelessWidget {
  final bool visible;
  final bool hasContent;
  final String? message;
  final String? technicalDetails;
  final int? lastUpdated;
  const LoadableStateErrorBar({
    required this.visible,
    this.hasContent = false,
    this.message,
    this.technicalDetails,
    this.lastUpdated,
    super.key,
  });

  final Duration animationDuration = const Duration(milliseconds: 200);

  @override
  Widget build(BuildContext context) {
    final bloc = context.watch<LoadableStateBloc>();
    final isOfflineWithCache =
        hasContent && bloc.connectivityStatusKnown() && !bloc.isConnected();
    final shouldShow = visible || isOfflineWithCache;

    return AnimatedSize(
      duration: animationDuration,
      child: AnimatedSwitcher(
        duration: animationDuration,
        transitionBuilder: (Widget child, Animation<double> animation) =>
            SlideTransition(
              position: Tween<Offset>(
                begin: const Offset(0.0, -1.0),
                end: Offset.zero,
              ).animate(animation),
              child: child,
            ),
        child: Visibility(
          key: Key(shouldShow.hashCode.toString()),
          visible: shouldShow,
          replacement: const SizedBox(width: double.infinity),
          child: Builder(
            builder: (context) {
              var bloc = context.watch<LoadableStateBloc>();
              return InkWell(
                onTap: () {
                  if (!bloc.isConnected()) return;
                  final body = [
                    if (message != null && message!.isNotEmpty) message!,
                    if (technicalDetails != null &&
                        technicalDetails!.isNotEmpty)
                      technicalDetails!,
                  ].join('\n\n');
                  if (body.isEmpty) return;
                  InfoDialog.show(
                    context,
                    body,
                    copyable: true,
                    title: 'Fehlerdetails',
                  );
                },
                child: Container(
                  height: 20,
                  decoration: BoxDecoration(
                    color: bloc.connectionColor(context),
                  ),
                  child: LoadableStateErrorBarText(lastUpdated: lastUpdated),
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

class LoadableStateErrorBarText extends StatefulWidget {
  final int? lastUpdated;
  const LoadableStateErrorBarText({required this.lastUpdated, super.key});

  @override
  State<LoadableStateErrorBarText> createState() =>
      _LoadableStateErrorBarTextState();
}

class _LoadableStateErrorBarTextState extends State<LoadableStateErrorBarText> {
  late Timer _rebuildTimer;
  @override
  void initState() {
    _rebuildTimer = Timer.periodic(
      const Duration(seconds: 10),
      (timer) => setState(() {}),
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var bloc = context.watch<LoadableStateBloc>();
    final foreground = bloc.connectionForegroundColor(context);

    // liveRegion, damit das Auftauchen des Offline-/Fehlerbanners angesagt wird;
    // Row-Semantik ausgeschlossen (Icon + Text) und Text über das explizite
    // Label getragen, sonst liest der Screenreader ihn doppelt.
    return Semantics(
      liveRegion: true,
      container: true,
      label: bloc.connectionText(lastUpdated: widget.lastUpdated),
      child: ExcludeSemantics(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(bloc.connectionIcon(), size: 14, color: foreground),
            const SizedBox(width: 10),
            Text(
              bloc.connectionText(lastUpdated: widget.lastUpdated),
              style: TextStyle(fontSize: 12, color: foreground),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _rebuildTimer.cancel();
    super.dispose();
  }
}
