import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:logging/logging.dart';
import 'package:relatica/models/exec_error.dart';
import 'package:result_monad/result_monad.dart';

import '../../globals.dart';
import '../../models/timeline_entry.dart';
import '../../models/visibility.dart' as v;
import '../../services/feature_version_checker.dart';
import '../../services/fediverse_server_validator.dart';
import '../../services/timeline_manager.dart';
import '../../utils/active_profile_selector.dart';
import '../../utils/snackbar_builder.dart';

class InteractionsBarControl extends StatefulWidget {
  final TimelineEntry entry;
  final bool showOpenControl;
  final bool isMine;

  const InteractionsBarControl({
    super.key,
    required this.entry,
    required this.isMine,
    required this.showOpenControl,
  });

  @override
  State<InteractionsBarControl> createState() => _InteractionsBarControlState();
}

class _InteractionsBarControlState extends State<InteractionsBarControl> {
  static final _logger = Logger('$InteractionsBarControl');

  var isProcessing = false;

  bool get isPost => widget.entry.parentId.isEmpty;

  bool get isFavorited => widget.entry.isFavorited;

  bool get youReshared => widget.entry.youReshared;

  int get reshares => widget.entry.engagementSummary.rebloggedCount;

  int get comments => widget.entry.engagementSummary.repliesCount;

  int get likes => widget.entry.engagementSummary.favoritesCount;

  Future<void> toggleFavorited() async {
    setState(() {
      isProcessing = true;
    });
    final newState = !isFavorited;
    _logger.fine('Trying to toggle favorite from $isFavorited to $newState');
    final result = await getIt<ActiveProfileSelector<TimelineManager>>()
        .activeEntry
        .andThenAsync(
            (tm) async => await tm.toggleFavorited(widget.entry.id, newState));
    result.match(onSuccess: (update) {
      setState(() {
        _logger.fine(
            'Success toggling! $isFavorited -> ${update.entry.isFavorited}');
      });
    }, onError: (error) {
      buildSnackbar(context, 'Error toggling like status: $error');
    });
    setState(() {
      isProcessing = false;
    });
  }

  Future<void> resharePost() async {
    setState(() {
      isProcessing = true;
    });

    final fvc = getIt<FriendicaVersionChecker>();
    if (!fvc.canUseFeature(RelaticaFeatures.diasporaReshare)) {
      final serverTypeEstimate = await getIt<FediverseServiceValidator>()
          .getServerData(widget.entry.externalLink)
          .fold(onSuccess: (d) => d.softwareName, onError: (_) => '');
      if (serverTypeEstimate ==
          FediverseServiceValidator.softwareTypeDiaspora) {
        if (mounted) {
          final error =
              fvc.versionErrorString(RelaticaFeatures.diasporaReshare);
          await showConfirmDialog(context, error);
        }
        setState(() {
          isProcessing = false;
        });
      }
    }

    final id = widget.entry.id;
    _logger.fine('Trying to reshare $id');
    final result = await getIt<ActiveProfileSelector<TimelineManager>>()
        .activeEntry
        .andThenAsync((tm) async => await tm.resharePost(id));

    result.match(onSuccess: (update) {
      setState(() {
        _logger.fine('Success resharing post by ${widget.entry.author}');
      });
    }, onError: (error) {
      buildSnackbar(context, 'Error resharing post by ${widget.entry.author}');
      logError(error, _logger);
    });
    setState(() {
      isProcessing = false;
    });
  }

  Future<void> addComment() async {
    if (mounted) {
      context.push('/comment/new?parent_id=${widget.entry.id}');
    }
  }

  Future<void> unResharePost() async {
    setState(() {
      isProcessing = true;
    });
    final id = widget.entry.id;
    _logger.fine('Trying to un-reshare $id');
    final result = await getIt<ActiveProfileSelector<TimelineManager>>()
        .activeEntry
        .andThenAsync((tm) async => await tm.unResharePost(id));
    result.match(onSuccess: (update) {
      setState(() {
        _logger.fine('Success un-resharing post by ${widget.entry.author}');
      });
    }, onError: (error) {
      buildSnackbar(
          context, 'Error un-resharing post by ${widget.entry.author}');
      logError(error, _logger);
    });
    setState(() {
      isProcessing = false;
    });
  }

  Widget buildButton(
    IconData icon,
    int count,
    bool isEnabled,
    String tooltip,
    Future Function()? onPressed,
  ) {
    return Row(
      children: [
        IconButton(
          onPressed: isEnabled && !isProcessing ? onPressed : null,
          icon: Icon(icon),
          tooltip: tooltip,
        ),
        Text('$count'),
      ],
    );
  }

  Widget buildLikeButton() {
    return buildButton(
      isFavorited ? Icons.thumb_up : Icons.thumb_up_outlined,
      likes,
      true,
      'Press to toggle like/unlike',
      () async => await toggleFavorited(),
    );
  }

  Widget buildCommentButton() {
    return buildButton(
      Icons.comment,
      comments,
      true,
      'Press to add a comment',
      () async => await addComment(),
    );
  }

  Widget buildReshareButton() {
    final canReshare = !widget.isMine &&
        widget.entry.visibility.type == v.VisibilityType.public;
    late final String tooltip;
    if (canReshare) {
      tooltip = youReshared ? 'Press to undo reshare' : 'Press to reshare';
    } else {
      if (widget.isMine) {
        tooltip = "Can't reshare your own post";
      } else if (widget.entry.visibility.type != v.VisibilityType.public) {
        tooltip = "Can't reshare a private post";
      } else {
        tooltip = "Can't reshare at this time";
      }
    }
    return buildButton(
      youReshared ? Icons.repeat_on_outlined : Icons.repeat,
      reshares,
      true,
      tooltip,
      canReshare && !isProcessing
          ? () async =>
              youReshared ? await unResharePost() : await resharePost()
          : null,
    );
  }

  @override
  Widget build(BuildContext context) {
    _logger.finest('Building: ${widget.entry.toShortString()}');
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        buildLikeButton(),
        buildCommentButton(),
        if (widget.entry.parentId.isEmpty) buildReshareButton(),
      ],
    );
  }
}
