import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';

import '../controls/html_text_viewer_control.dart';
import '../controls/login_aware_cached_network_image.dart';
import '../controls/padding.dart';
import '../globals.dart';
import '../models/circle_data.dart';
import '../models/connection.dart';
import '../routes.dart';
import '../services/auth_service.dart';
import '../services/blocks_manager.dart';
import '../services/connections_manager.dart';
import '../utils/active_profile_selector.dart';
import '../utils/snackbar_builder.dart';
import '../utils/url_opening_utils.dart';

class UserProfileScreen extends StatefulWidget {
  final String userId;

  const UserProfileScreen({super.key, required this.userId});

  @override
  State<UserProfileScreen> createState() => _UserProfileScreenState();
}

class _UserProfileScreenState extends State<UserProfileScreen> {
  var isUpdating = false;

  @override
  void initState() {
    super.initState();
    getIt<ActiveProfileSelector<ConnectionsManager>>().activeEntry.withResult(
          (m) => m.getById(widget.userId, forceUpdate: true),
        );
  }

  @override
  Widget build(BuildContext context) {
    final connectionManager = context
        .watch<ActiveProfileSelector<ConnectionsManager>>()
        .activeEntry
        .value;
    final blocksManager =
        context.watch<ActiveProfileSelector<BlocksManager>>().activeEntry.value;
    final body =
        connectionManager.getById(widget.userId).fold(onSuccess: (profile) {
      final notMyProfile =
          getIt<AccountsService>().currentProfile.userId != profile.id;

      return RefreshIndicator(
        onRefresh: () async {
          await connectionManager.fullRefresh(profile,
              withNotifications: false);
          await blocksManager.updateBlock(profile);
        },
        child: SingleChildScrollView(
          physics: const AlwaysScrollableScrollPhysics(),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              LoginAwareCachedNetworkImage(
                  imageUrl: profile.avatarUrl.toString()),
              const Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [],
              ),
              Text(
                notMyProfile
                    ? '${profile.name} (${profile.handle})'
                    : '${profile.name} (Your Account)',
                softWrap: true,
                textAlign: TextAlign.center,
                style: Theme.of(context).textTheme.titleLarge,
              ),
              const VerticalPadding(),
              Text('( ${profile.status.label()} )'),
              const VerticalPadding(),
              Wrap(
                spacing: 10.0,
                runSpacing: 10.0,
                children: [
                  ElevatedButton(
                      onPressed: () => context.pushNamed(
                            ScreenPaths.userPosts,
                            pathParameters: {'id': profile.id},
                          ),
                      child: const Text('Posts')),
                  ElevatedButton(
                    onPressed: () async =>
                        await openProfileExternal(context, profile),
                    child: const Text('Open In Browser'),
                  ),
                ],
              ),
              const VerticalPadding(),
              Wrap(
                spacing: 10.0,
                runSpacing: 10.0,
                children: [
                  if (notMyProfile) ...[
                    buildConnectionStatusToggle(
                        context, profile, connectionManager),
                    buildBlockToggle(context, profile, blocksManager),
                  ],
                ],
              ),
              const VerticalPadding(),
              HtmlTextViewerControl(
                content: profile.note,
                onTapUrl: (url) async {
                  return await openUrlStringInSystembrowser(
                      context, url, 'link');
                },
              ),
              const VerticalPadding(),
              Text(
                  '#Followers: ${profile.followerCount} followers, #Following, ${profile.followingCount}, #Statuses: ${profile.statusesCount}'),
              const VerticalPadding(),
              Text('Last Status: ${profile.lastStatus ?? "Unknown"}'),
              const VerticalPadding(),
              if (profile.status == ConnectionStatus.mutual ||
                  profile.status == ConnectionStatus.youFollowThem)
                buildCircles(context, profile, connectionManager),
            ],
          ),
        ),
      );
    }, onError: (error) {
      return Text('Error getting profile: $error');
    });
    return Scaffold(
      appBar: AppBar(
        title: const Text('Profile'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Center(
          child: body,
        ),
      ),
    );
  }

  Widget buildCircles(
    BuildContext context,
    Connection profile,
    ConnectionsManager manager,
  ) {
    final myCircles = manager.getMyCircles();
    final usersCircles = manager.getCirclesForUser(profile.id).fold(
        onSuccess: (circles) => circles.toSet(),
        onError: (error) {
          buildSnackbar(context, 'Error getting circle data: $error');
          return <CircleData>{};
        });
    myCircles.sort((g1, g2) => g1.name.compareTo(g2.name));
    final circlesWidgets = myCircles.map((g) {
      return CheckboxListTile(
        title: Text(g.name),
        value: usersCircles.contains(g),
        onChanged: (bool? value) async {
          if (isUpdating) {
            return;
          }

          final isAdding = value == true;
          final confirm = await showYesNoDialog(
              context,
              isAdding
                  ? 'Add user to ${g.name}'
                  : 'Remove user from ${g.name}');
          if (confirm != true) {
            return;
          }
          setState(() {
            isUpdating = true;
          });
          if (isAdding) {
            await manager.addUserToCircle(g, profile);
          } else {
            await manager.removeUserFromCircle(g, profile);
          }
          setState(() {
            isUpdating = false;
          });
        },
      );
    }).toList();
    return Column(
      children: [
        Text(
          'Circles: ',
          style: Theme.of(context).textTheme.titleMedium,
        ),
        const VerticalPadding(),
        ...circlesWidgets,
      ],
    );
  }

  Widget buildBlockToggle(
    BuildContext context,
    Connection profile,
    BlocksManager manager,
  ) {
    late Widget blockToggleButton;
    switch (profile.status) {
      case ConnectionStatus.blocked:
        blockToggleButton = ElevatedButton(
          onPressed: isUpdating
              ? null
              : () async {
                  final confirm =
                      await showYesNoDialog(context, 'Unblock ${profile.name}');
                  if (confirm != true) {
                    return;
                  }
                  setState(() {
                    isUpdating = true;
                  });
                  await manager.unblockConnection(profile);
                  setState(() {
                    isUpdating = false;
                  });
                },
          child: const Text('Unblock'),
        );
        break;
      case ConnectionStatus.mutual:
      case ConnectionStatus.theyFollowYou:
      case ConnectionStatus.youFollowThem:
      case ConnectionStatus.none:
      case ConnectionStatus.unknown:
        blockToggleButton = ElevatedButton(
          onPressed: isUpdating
              ? null
              : () async {
                  final confirm =
                      await showYesNoDialog(context, 'Block ${profile.name}');
                  if (confirm != true) {
                    return;
                  }
                  setState(() {
                    isUpdating = true;
                  });
                  await manager.blockConnection(profile);
                  setState(() {
                    isUpdating = false;
                  });
                },
          child: const Text('Block'),
        );
        break;
      case ConnectionStatus.you:
        blockToggleButton = const SizedBox();
        break;
    }
    return blockToggleButton;
  }

  Widget buildConnectionStatusToggle(
    BuildContext context,
    Connection profile,
    ConnectionsManager manager,
  ) {
    late Widget followToggleButton;
    switch (profile.status) {
      case ConnectionStatus.mutual:
      case ConnectionStatus.youFollowThem:
        followToggleButton = ElevatedButton(
          onPressed: isUpdating
              ? null
              : () async {
                  final confirm = await showYesNoDialog(
                      context, 'Unfollow ${profile.name}');
                  if (confirm != true) {
                    return;
                  }
                  setState(() {
                    isUpdating = true;
                  });
                  await manager.unfollow(profile);
                  setState(() {
                    isUpdating = false;
                  });
                },
          child: const Text('Unfollow'),
        );
        break;
      case ConnectionStatus.theyFollowYou:
      case ConnectionStatus.none:
        followToggleButton = ElevatedButton(
          onPressed: isUpdating
              ? null
              : () async {
                  final confirm =
                      await showYesNoDialog(context, 'Follow ${profile.name}');
                  if (confirm != true) {
                    return;
                  }
                  setState(() {
                    isUpdating = true;
                  });
                  await manager.follow(profile);
                  setState(() {
                    isUpdating = false;
                  });
                },
          child: const Text('Follow'),
        );
        break;
      case ConnectionStatus.blocked:
      case ConnectionStatus.you:
      case ConnectionStatus.unknown:
        followToggleButton = const SizedBox();
        break;
    }
    return followToggleButton;
  }
}
