import 'package:auto_route/auto_route.dart';
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/chat.dart';
import 'package:island/pods/network.dart';
import 'package:island/route.gr.dart';
import 'package:island/screens/chat/chat.dart';
import 'package:island/widgets/account/account_picker.dart';
import 'package:island/widgets/alert.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';

part 'room_detail.freezed.dart';

@RoutePage()
class ChatDetailScreen extends HookConsumerWidget {
  final String id;
  const ChatDetailScreen({super.key, @PathParam("id") required this.id});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final roomState = ref.watch(chatroomProvider(id));

    const iconShadow = Shadow(
      color: Colors.black54,
      blurRadius: 5.0,
      offset: Offset(1.0, 1.0),
    );

    return AppScaffold(
      body: roomState.when(
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (error, _) => Center(child: Text('Error: $error')),
        data:
            (currentRoom) => CustomScrollView(
              slivers: [
                SliverAppBar(
                  expandedHeight: 180,
                  pinned: true,
                  leading: PageBackButton(shadows: [iconShadow]),
                  flexibleSpace: FlexibleSpaceBar(
                    background:
                        (currentRoom!.type == 1 &&
                                currentRoom.backgroundId != null)
                            ? CloudImageWidget(
                              fileId: currentRoom.backgroundId!,
                            )
                            : (currentRoom.type == 1 &&
                                currentRoom.members!.length == 1 &&
                                currentRoom
                                        .members!
                                        .first
                                        .account
                                        .profile
                                        .backgroundId !=
                                    null)
                            ? CloudImageWidget(
                              fileId:
                                  currentRoom
                                      .members!
                                      .first
                                      .account
                                      .profile
                                      .backgroundId!,
                            )
                            : currentRoom.backgroundId != null
                            ? CloudImageWidget(
                              fileId: currentRoom.backgroundId!,
                              fit: BoxFit.cover,
                            )
                            : Container(
                              color:
                                  Theme.of(context).appBarTheme.backgroundColor,
                            ),
                    title: Text(
                      (currentRoom.type == 1 && currentRoom.name == null)
                          ? currentRoom.members!
                              .map((e) => e.account.nick)
                              .join(', ')
                          : currentRoom.name!,
                      style: TextStyle(
                        color: Theme.of(context).appBarTheme.foregroundColor,
                        shadows: [iconShadow],
                      ),
                    ),
                  ),
                  actions: [
                    IconButton(
                      icon: const Icon(Icons.people, shadows: [iconShadow]),
                      onPressed: () {
                        showModalBottomSheet(
                          isScrollControlled: true,
                          context: context,
                          builder:
                              (context) => _ChatMemberListSheet(roomId: id),
                        );
                      },
                    ),
                    _ChatRoomActionMenu(id: id, iconShadow: iconShadow),
                    const Gap(8),
                  ],
                ),
                SliverToBoxAdapter(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          currentRoom.description ?? 'descriptionNone'.tr(),
                          style: const TextStyle(fontSize: 16),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
      ),
    );
  }
}

class _ChatRoomActionMenu extends HookConsumerWidget {
  final String id;
  final Shadow iconShadow;

  const _ChatRoomActionMenu({required this.id, required this.iconShadow});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final chatIdentity = ref.watch(chatroomIdentityProvider(id));

    return PopupMenuButton(
      icon: Icon(Icons.more_vert, shadows: [iconShadow]),
      itemBuilder:
          (context) => [
            if ((chatIdentity.value?.role ?? 0) >= 50)
              PopupMenuItem(
                onTap: () {
                  context.router.replace(EditChatRoute(id: id));
                },
                child: Row(
                  children: [
                    Icon(
                      Icons.edit,
                      color: Theme.of(context).colorScheme.onSecondaryContainer,
                    ),
                    const Gap(12),
                    const Text('editChatRoom').tr(),
                  ],
                ),
              ),
            if ((chatIdentity.value?.role ?? 0) >= 100)
              PopupMenuItem(
                child: Row(
                  children: [
                    const Icon(Icons.delete, color: Colors.red),
                    const Gap(12),
                    const Text(
                      'deleteChatRoom',
                      style: TextStyle(color: Colors.red),
                    ).tr(),
                  ],
                ),
                onTap: () {
                  showConfirmAlert(
                    'deleteChatRoomHint'.tr(),
                    'deleteChatRoom'.tr(),
                  ).then((confirm) {
                    if (confirm) {
                      final client = ref.watch(apiClientProvider);
                      client.delete('/chat/$id');
                      ref.invalidate(chatroomsJoinedProvider);
                      if (context.mounted) {
                        context.router.popUntil(
                          (route) => route is ChatRoomRoute,
                        );
                      }
                    }
                  });
                },
              )
            else
              PopupMenuItem(
                child: Row(
                  children: [
                    Icon(
                      Icons.exit_to_app,
                      color: Theme.of(context).colorScheme.error,
                    ),
                    const Gap(12),
                    Text(
                      'leaveChatRoom',
                      style: TextStyle(
                        color: Theme.of(context).colorScheme.error,
                      ),
                    ).tr(),
                  ],
                ),
                onTap: () {
                  showConfirmAlert(
                    'leaveChatRoomHint'.tr(),
                    'leaveChatRoom'.tr(),
                  ).then((confirm) {
                    if (confirm) {
                      final client = ref.watch(apiClientProvider);
                      client.delete('/chat/$id/members/me');
                      ref.invalidate(chatroomsJoinedProvider);
                      if (context.mounted) {
                        context.router.popUntil(
                          (route) => route is ChatRoomRoute,
                        );
                      }
                    }
                  });
                },
              ),
          ],
    );
  }
}

@freezed
abstract class ChatRoomMemberState with _$ChatRoomMemberState {
  const factory ChatRoomMemberState({
    required List<SnChatMember> members,
    required bool isLoading,
    required int total,
    String? error,
  }) = _ChatRoomMemberState;
}

final chatMemberStateProvider = StateNotifierProvider.family<
  ChatMemberNotifier,
  ChatRoomMemberState,
  String
>((ref, roomId) {
  final apiClient = ref.watch(apiClientProvider);
  return ChatMemberNotifier(apiClient, roomId);
});

class ChatMemberNotifier extends StateNotifier<ChatRoomMemberState> {
  final String roomId;
  final Dio _apiClient;

  ChatMemberNotifier(this._apiClient, this.roomId)
    : super(const ChatRoomMemberState(members: [], isLoading: false, total: 0));

  Future<void> loadMore({int offset = 0, int take = 20}) async {
    if (state.isLoading) return;
    if (state.total > 0 && state.members.length >= state.total) return;

    state = state.copyWith(isLoading: true, error: null);

    try {
      final response = await _apiClient.get(
        '/chat/$roomId/members',
        queryParameters: {'offset': offset, 'take': take},
      );

      final total = int.parse(response.headers.value('X-Total') ?? '0');
      final List<dynamic> data = response.data;
      final members = data.map((e) => SnChatMember.fromJson(e)).toList();

      state = state.copyWith(
        members: [...state.members, ...members],
        total: total,
        isLoading: false,
      );
    } catch (e) {
      state = state.copyWith(error: e.toString(), isLoading: false);
    }
  }

  void reset() {
    state = const ChatRoomMemberState(members: [], isLoading: false, total: 0);
  }
}

class _ChatMemberListSheet extends HookConsumerWidget {
  final String roomId;
  const _ChatMemberListSheet({required this.roomId});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final memberState = ref.watch(chatMemberStateProvider(roomId));
    final memberNotifier = ref.read(chatMemberStateProvider(roomId).notifier);

    final roomIdentity = ref.watch(chatroomIdentityProvider(roomId));

    useEffect(() {
      Future(() {
        memberNotifier.loadMore();
      });
      return null;
    }, []);

    Future<void> invitePerson() async {
      final result = await showModalBottomSheet(
        isScrollControlled: true,
        context: context,
        builder: (context) => const AccountPickerSheet(),
      );
      if (result == null) return;
      try {
        final apiClient = ref.watch(apiClientProvider);
        await apiClient.post(
          '/chat/invites/$roomId',
          data: {'related_user_id': result.id, 'role': 0},
        );
        memberNotifier.reset();
        await memberNotifier.loadMore();
      } catch (err) {
        showErrorAlert(err);
      }
    }

    return Container(
      constraints: BoxConstraints(
        maxHeight: MediaQuery.of(context).size.height * 0.8,
      ),
      child: Column(
        children: [
          Padding(
            padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
            child: Row(
              children: [
                Text(
                  'members'.plural(memberState.total),
                  style: Theme.of(context).textTheme.headlineSmall?.copyWith(
                    fontWeight: FontWeight.w600,
                    letterSpacing: -0.5,
                  ),
                ),
                const Spacer(),
                IconButton(
                  icon: const Icon(Symbols.person_add),
                  onPressed: invitePerson,
                  style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
                ),
                IconButton(
                  icon: const Icon(Symbols.refresh),
                  onPressed: () {
                    memberNotifier.reset();
                    memberNotifier.loadMore();
                  },
                ),
                IconButton(
                  icon: const Icon(Symbols.close),
                  onPressed: () => Navigator.pop(context),
                  style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
                ),
              ],
            ),
          ),
          const Divider(height: 1),
          Expanded(
            child:
                memberState.error != null
                    ? Center(child: Text(memberState.error!))
                    : ListView.builder(
                      itemCount: memberState.members.length + 1,
                      itemBuilder: (context, index) {
                        if (index == memberState.members.length) {
                          if (memberState.isLoading) {
                            return const Center(
                              child: Padding(
                                padding: EdgeInsets.all(16.0),
                                child: CircularProgressIndicator(),
                              ),
                            );
                          }
                          if (memberState.members.length < memberState.total) {
                            memberNotifier.loadMore(
                              offset: memberState.members.length,
                            );
                          }
                          return const SizedBox.shrink();
                        }

                        final member = memberState.members[index];
                        return ListTile(
                          contentPadding: EdgeInsets.only(left: 16, right: 12),
                          leading: ProfilePictureWidget(
                            fileId: member.account.profile.pictureId,
                          ),
                          title: Row(
                            spacing: 6,
                            children: [
                              Flexible(child: Text(member.account.nick)),
                              if (member.joinedAt == null)
                                const Icon(Symbols.pending_actions, size: 20),
                            ],
                          ),
                          subtitle: Row(
                            children: [
                              Text(
                                member.role >= 100
                                    ? 'permissionOwner'
                                    : member.role >= 50
                                    ? 'permissionModerator'
                                    : 'permissionMember',
                              ).tr(),
                              Text('ยท').bold().padding(horizontal: 6),
                              Expanded(child: Text("@${member.account.name}")),
                            ],
                          ),
                          trailing: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              if ((roomIdentity.value?.role ?? 0) >= 50)
                                IconButton(
                                  icon: const Icon(Symbols.edit),
                                  onPressed: () {
                                    showModalBottomSheet(
                                      isScrollControlled: true,
                                      context: context,
                                      builder:
                                          (context) => _ChatMemberRoleSheet(
                                            roomId: roomId,
                                            member: member,
                                          ),
                                    ).then((value) {
                                      if (value != null) {
                                        memberNotifier.reset();
                                        memberNotifier.loadMore();
                                      }
                                    });
                                  },
                                ),
                              if ((roomIdentity.value?.role ?? 0) >= 50)
                                IconButton(
                                  icon: const Icon(Symbols.delete),
                                  onPressed: () {
                                    showConfirmAlert(
                                      'removeChatMemberHint'.tr(),
                                      'removeChatMember'.tr(),
                                    ).then((confirm) async {
                                      if (confirm != true) return;
                                      try {
                                        final apiClient = ref.watch(
                                          apiClientProvider,
                                        );
                                        await apiClient.delete(
                                          '/chat/$roomId/members/${member.accountId}',
                                        );
                                        memberNotifier.reset();
                                        memberNotifier.loadMore();
                                      } catch (err) {
                                        showErrorAlert(err);
                                      }
                                    });
                                  },
                                ),
                            ],
                          ),
                        );
                      },
                    ),
          ),
        ],
      ),
    );
  }
}

class _ChatMemberRoleSheet extends HookConsumerWidget {
  final String roomId;
  final SnChatMember member;

  const _ChatMemberRoleSheet({required this.roomId, required this.member});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final roleController = useTextEditingController(
      text: member.role.toString(),
    );

    return Container(
      padding: EdgeInsets.only(
        bottom: MediaQuery.of(context).viewInsets.bottom,
      ),
      child: SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Padding(
              padding: EdgeInsets.only(
                top: 16,
                left: 20,
                right: 16,
                bottom: 12,
              ),
              child: Row(
                children: [
                  Text(
                    'memberRoleEdit'.tr(args: [member.account.name]),
                    style: Theme.of(context).textTheme.headlineSmall?.copyWith(
                      fontWeight: FontWeight.w600,
                      letterSpacing: -0.5,
                    ),
                  ),
                  const Spacer(),
                  IconButton(
                    icon: const Icon(Symbols.close),
                    onPressed: () => Navigator.pop(context),
                    style: IconButton.styleFrom(
                      minimumSize: const Size(36, 36),
                    ),
                  ),
                ],
              ),
            ),
            const Divider(height: 1),
            Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Autocomplete<int>(
                  optionsBuilder: (TextEditingValue textEditingValue) {
                    if (textEditingValue.text.isEmpty) {
                      return const [100, 50, 0];
                    }
                    final int? value = int.tryParse(textEditingValue.text);
                    if (value == null) return const [100, 50, 0];
                    return [100, 50, 0].where(
                      (option) =>
                          option.toString().contains(textEditingValue.text),
                    );
                  },
                  onSelected: (int selection) {
                    roleController.text = selection.toString();
                  },
                  fieldViewBuilder: (
                    context,
                    controller,
                    focusNode,
                    onFieldSubmitted,
                  ) {
                    return TextField(
                      controller: controller,
                      focusNode: focusNode,
                      keyboardType: TextInputType.number,
                      decoration: InputDecoration(
                        labelText: 'memberRole'.tr(),
                        helperText: 'memberRoleHint'.tr(),
                      ),
                      onTapOutside: (event) => focusNode.unfocus(),
                    );
                  },
                ),
                const Gap(16),
                FilledButton.icon(
                  onPressed: () async {
                    try {
                      final newRole = int.parse(roleController.text);
                      if (newRole < 0 || newRole > 100) {
                        throw 'Role must be between 0 and 100';
                      }

                      final apiClient = ref.read(apiClientProvider);
                      await apiClient.patch(
                        '/chat/$roomId/members/${member.accountId}/role',
                        data: newRole,
                      );

                      if (context.mounted) Navigator.pop(context, true);
                    } catch (err) {
                      showErrorAlert(err);
                    }
                  },
                  icon: const Icon(Symbols.save),
                  label: const Text('saveChanges').tr(),
                ),
              ],
            ).padding(vertical: 16, horizontal: 24),
          ],
        ),
      ),
    );
  }
}