import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'
    show
        HookWidget,
        useAnimationController,
        useEffect,
        useFocusNode,
        useMemoized,
        useScrollController,
        useState,
        useTextEditingController;
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart' show Gap;
import 'package:hooks_riverpod/hooks_riverpod.dart' show HookConsumerWidget, WidgetRef;
import 'package:unique_names_generator/unique_names_generator.dart';
import 'package:whitenoise/hooks/use_image_picker.dart';
import 'package:whitenoise/hooks/use_onboarding_carousel.dart' show onboardingCarouselSlideCount;
import 'package:whitenoise/hooks/use_signup.dart' show useSignup;
import 'package:whitenoise/l10n/l10n.dart';
import 'package:whitenoise/providers/auth_provider.dart' show authProvider;
import 'package:whitenoise/providers/offline_provider.dart' show offlineProvider;
import 'package:whitenoise/routes.dart' show Routes;
import 'package:whitenoise/theme.dart';
import 'package:whitenoise/widgets/offline_system_notice.dart';
import 'package:whitenoise/widgets/wn_avatar.dart' show WnAvatar, WnAvatarSize;
import 'package:whitenoise/widgets/wn_button.dart';
import 'package:whitenoise/widgets/wn_callout.dart';
import 'package:whitenoise/widgets/wn_carousel_indicator.dart' show WnCarouselIndicator;
import 'package:whitenoise/widgets/wn_icon.dart' show WnIcon, WnIcons;
import 'package:whitenoise/widgets/wn_input.dart' show WnInput;
import 'package:whitenoise/widgets/wn_input_text_area.dart' show WnInputTextArea;
import 'package:whitenoise/widgets/wn_onboarding_carousel.dart' show WnOnboardingCarousel;
import 'package:whitenoise/widgets/wn_slate.dart';
import 'package:whitenoise/widgets/wn_slate_navigation_header.dart';
import 'package:whitenoise/widgets/wn_system_notice.dart';

class SignupScreen extends HookConsumerWidget {
  const SignupScreen({super.key});

  static const _animationDuration = Duration(milliseconds: 350);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final colors = context.colors;
    final isOffline = ref.watch(offlineProvider).value ?? false;
    final generatedDisplayName = useMemoized(() {
      final generator = UniqueNamesGenerator(
        config: Config(
          length: 2,
          dictionaries: [adjectives, animals],
          separator: ' ',
          style: Style.capital,
        ),
      );
      return generator.generate();
    });
    final displayNameController = useTextEditingController(
      text: generatedDisplayName,
    );
    final bioController = useTextEditingController();
    final bioFocusNode = useFocusNode();
    final scrollController = useScrollController();
    final (:state, :submit, :onImageSelected, :clearErrors) = useSignup(
      () => ref.read(authProvider.notifier).signup(),
    );
    final (
      :pickImage,
      error: imagePickerError,
      clearError: clearImagePickerError,
    ) = useImagePicker(
      onImageSelected: onImageSelected,
    );
    final noticeMessage = useState<String?>(null);
    final privacyNoticeExpanded = useState(false);
    final showCarousel = useState(false);
    final carouselIndex = useState(0);
    final carouselAccentColor = useState<Color>(
      context.colors.accent.cyan.contentSecondary,
    );

    final carouselAnimationController = useAnimationController(
      duration: _animationDuration,
    );

    void showNotice(String message) {
      noticeMessage.value = message;
    }

    void dismissNotice() {
      noticeMessage.value = null;
    }

    void openCarousel() {
      showCarousel.value = true;
      carouselAnimationController.forward();
    }

    void closeCarousel() {
      carouselAnimationController.reverse().then((_) {
        showCarousel.value = false;
      });
    }

    useEffect(() {
      if (imagePickerError != null) {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (context.mounted) {
            showNotice(context.l10n.imagePickerError);
          }
        });
        clearImagePickerError();
      }
      return null;
    }, [imagePickerError]);

    useEffect(() {
      var isActive = true;

      void onBioFocusChange() {
        if (bioFocusNode.hasFocus && scrollController.hasClients) {
          Future.delayed(const Duration(milliseconds: 300), () {
            if (!isActive || !bioFocusNode.hasFocus || !scrollController.hasClients) return;
            final currentOffset = scrollController.offset;
            final maxOffset = scrollController.position.maxScrollExtent;
            final targetOffset = (currentOffset + 60.h).clamp(0.0, maxOffset);
            scrollController.animateTo(
              targetOffset,
              duration: const Duration(milliseconds: 200),
              curve: Curves.easeOut,
            );
          });
        }
      }

      bioFocusNode.addListener(onBioFocusChange);
      return () {
        isActive = false;
        bioFocusNode.removeListener(onBioFocusChange);
      };
    }, [bioFocusNode, scrollController]);

    Future<void> onSubmit() async {
      final success = await submit(
        displayName: displayNameController.text.trim(),
        bio: bioController.text.trim(),
      );
      if (success && context.mounted) {
        Routes.goToChatList(context);
      }
    }

    final slideAnimation = Tween<Offset>(begin: Offset.zero, end: const Offset(0, 1)).animate(
      CurvedAnimation(
        parent: carouselAnimationController,
        curve: Curves.easeInOut,
      ),
    );

    final fadeAnimation = CurvedAnimation(
      parent: carouselAnimationController,
      curve: Curves.easeInOut,
    );

    return Scaffold(
      backgroundColor: colors.backgroundPrimary,
      body: Stack(
        fit: StackFit.expand,
        children: [
          Positioned.fill(
            child: IgnorePointer(
              ignoring: showCarousel.value,
              child: GestureDetector(
                key: const Key('signup_background'),
                onTap: () => Routes.goBack(context),
                behavior: HitTestBehavior.translucent,
              ),
            ),
          ),
          SafeArea(
            child: FadeTransition(
              opacity: CurvedAnimation(
                parent: ModalRoute.of(context)?.animation ?? kAlwaysCompleteAnimation,
                curve: const Interval(0.5, 1.0),
              ),
              child: Align(
                alignment: Alignment.topCenter,
                child: SizedBox(
                  height: 148.h,
                  child: Center(
                    child: _LearnMoreButton(
                      key: const Key('learn_more_button'),
                      onTap: openCarousel,
                      visible: !showCarousel.value,
                    ),
                  ),
                ),
              ),
            ),
          ),
          SafeArea(
            child: Column(
              children: [
                SizedBox(
                  height: (148.h - MediaQuery.of(context).viewInsets.bottom).clamp(0.0, 148.h),
                ),
                Expanded(
                  child: FadeTransition(
                    opacity: ReverseAnimation(fadeAnimation),
                    child: SlideTransition(
                      position: slideAnimation,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: [
                          Flexible(
                            child: WnSlate(
                              header: WnSlateNavigationHeader(
                                title: context.l10n.setupProfile,
                                onNavigate: () => Routes.goBack(context),
                              ),
                              systemNotice: isOffline
                                  ? const OfflineSystemNotice()
                                  : (noticeMessage.value != null)
                                  ? WnSystemNotice(
                                      key: ValueKey(noticeMessage.value),
                                      title: noticeMessage.value!,
                                      type: WnSystemNoticeType.error,
                                      onDismiss: dismissNotice,
                                    )
                                  : null,
                              footer: Padding(
                                padding: EdgeInsets.only(
                                  left: 14.w,
                                  right: 14.w,
                                  bottom: 14.h,
                                ),
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.stretch,
                                  children: [
                                    ValueListenableBuilder(
                                      valueListenable: displayNameController,
                                      builder: (context, value, child) {
                                        final hasName = value.text.trim().isNotEmpty;
                                        return WnButton(
                                          key: const Key(
                                            'signup_create_profile_button',
                                          ),
                                          text: context.l10n.createProfile,
                                          onPressed: hasName && !isOffline ? onSubmit : null,
                                          loading: state.isLoading,
                                          disabled: !hasName || state.isLoading || isOffline,
                                        );
                                      },
                                    ),
                                  ],
                                ),
                              ),
                              child: SingleChildScrollView(
                                controller: scrollController,
                                child: Padding(
                                  padding: EdgeInsets.fromLTRB(
                                    14.w,
                                    8.h,
                                    14.w,
                                    14.h,
                                  ),
                                  child: Column(
                                    mainAxisSize: MainAxisSize.min,
                                    crossAxisAlignment: CrossAxisAlignment.stretch,
                                    children: [
                                      Center(
                                        child: ValueListenableBuilder(
                                          valueListenable: displayNameController,
                                          builder: (context, value, child) {
                                            return WnAvatar(
                                              pictureUrl: state.selectedImagePath,
                                              displayName: value.text,
                                              size: WnAvatarSize.large,
                                              onEditTap: state.isLoading ? null : pickImage,
                                            );
                                          },
                                        ),
                                      ),
                                      Gap(16.h),
                                      WnCallout(
                                        key: const Key('signup_privacy_notice'),
                                        title: context.l10n.profileIsPublic,
                                        description: privacyNoticeExpanded.value
                                            ? context.l10n.profilePrivacyDescription
                                            : null,
                                        isExpanded: privacyNoticeExpanded.value,
                                        onToggle: () {
                                          privacyNoticeExpanded.value =
                                              !privacyNoticeExpanded.value;
                                        },
                                      ),
                                      Gap(16.h),
                                      WnInput(
                                        key: const Key(
                                          'signup_display_name_field',
                                        ),
                                        label: context.l10n.chooseName,
                                        placeholder: context.l10n.enterYourName,
                                        controller: displayNameController,
                                        errorText: state.displayNameError,
                                        onChanged: (_) => clearErrors(),
                                      ),
                                      Gap(16.h),
                                      WnInputTextArea(
                                        key: const Key('signup_bio_field'),
                                        label: context.l10n.introduceYourself,
                                        placeholder: context.l10n.writeSomethingAboutYourself,
                                        controller: bioController,
                                        focusNode: bioFocusNode,
                                        textInputAction: TextInputAction.done,
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          ),
                          SizedBox(
                            height: MediaQuery.of(
                              context,
                            ).viewInsets.bottom.clamp(0.0, 16.h),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
          Positioned.fill(
            child: IgnorePointer(
              ignoring: !showCarousel.value,
              child: FadeTransition(
                opacity: fadeAnimation,
                child: SafeArea(
                  child: Column(
                    children: [
                      const Spacer(),
                      WnOnboardingCarousel(
                        key: const Key('signup_onboarding_carousel'),
                        height: 260.h,
                        onSlideChanged: (index, accentColor) {
                          carouselIndex.value = index;
                          carouselAccentColor.value = accentColor;
                        },
                      ),
                      SizedBox(height: 16.h),
                      WnCarouselIndicator(
                        key: const Key('signup_carousel_indicator'),
                        itemCount: onboardingCarouselSlideCount,
                        activeIndex: carouselIndex.value,
                        activeColor: carouselAccentColor.value,
                      ),
                      SizedBox(height: 287.h),
                      WnSlate(
                        tag: 'wn-slate-carousel',
                        child: Padding(
                          padding: EdgeInsets.symmetric(
                            vertical: 14.h,
                            horizontal: 14.w,
                          ),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.stretch,
                            children: [
                              WnButton(
                                key: const Key('back_to_signup_button'),
                                text: context.l10n.backToSignUp,
                                type: WnButtonType.outline,
                                trailingIcon: WnIcons.arrowDown,
                                onPressed: closeCarousel,
                              ),
                            ],
                          ),
                        ),
                      ),
                      SizedBox(height: 10.h),
                    ],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _LearnMoreButton extends HookWidget {
  const _LearnMoreButton({
    super.key,
    required this.onTap,
    required this.visible,
  });

  final VoidCallback onTap;
  final bool visible;

  @override
  Widget build(BuildContext context) {
    final colors = context.colors;
    final typography = context.typographyScaled;
    final l10n = context.l10n;

    return AnimatedOpacity(
      opacity: visible ? 1.0 : 0.0,
      duration: const Duration(milliseconds: 200),
      child: IgnorePointer(
        ignoring: !visible,
        child: GestureDetector(
          onTap: onTap,
          behavior: HitTestBehavior.opaque,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              WnIcon(
                WnIcons.arrowUp,
                key: const Key('learn_more_arrow'),
                size: 20.sp,
                color: colors.backgroundContentPrimary,
              ),
              SizedBox(height: 4.h),
              Text(
                l10n.learnMore,
                style: typography.medium14.copyWith(
                  color: colors.backgroundContentPrimary,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
