'use client';

import { useGateValue } from '@statsig/react-bindings';
import clsx from 'clsx';
import { usePathname } from 'next/navigation';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useDebounceValue } from 'usehooks-ts';

import { useStores } from '@/app/(root)/AppProviders';
import Avatar from '@/components/image/Avatar';
import { ImageSize } from '@/components/image/ImageWithFallback';
import Modal from '@/components/modal/Modal';
import { ModalTypes } from '@/components/modal/constants/ModalTypes';
import TextareaV2 from '@/components/textarea/TextareaV2';
import { toast } from '@/components/toast/Toast';
import { useModalContext } from '@/context/ModalContext';
import { useMutualFollowerSearch } from '@/hooks/useComments';
import { useApiClient } from '@/lib/apiClient';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { eventLogger } from '@/utils/event-logger';
import { ActionName } from '@/utils/event-names';
import { getShareLink } from '@/utils/share';

const ShareWithFriendsModal: React.FC = () => {
  const { session, clips } = useStores();
  const { closeModal, getModalData, getModalSource } = useModalContext();

  // Get modal data and source
  const modalData = getModalData(ModalTypes.SHARE_WITH_FRIENDS);
  const modalSource = getModalSource(ModalTypes.SHARE_WITH_FRIENDS);

  // Get the clip from the clipId
  const song = modalData?.clipId ? clips.clipById[modalData.clipId] : undefined;
  const pathname = usePathname();
  const apiClient = useApiClient();

  const showInAppSharing = useGateValue(
    'enable-sharelist-and-share-notifications'
  );

  // User search state
  const [userSearchInput, setUserSearchInput] = useState('');
  const [debouncedUserSearch] = useDebounceValue(userSearchInput, 300);
  const [showUserDropdown, setShowUserDropdown] = useState(true);
  const [isSharingWithUser, setIsSharingWithUser] = useState(false);
  const [selectedUserIndex, setSelectedUserIndex] = useState(0);
  const [showLoadingMessage, setShowLoadingMessage] = useState(false);
  const userInputRef = useRef<HTMLTextAreaElement>(null);
  const userItemRefs = useRef<(HTMLButtonElement | null)[]>([]);

  // Use mutual follower search hook (only shows users who are both followers and following)
  // Only fetch when the modal is actually open (enabled: true when component is mounted)
  const { suggestedUsers, query: mutualFollowersQuery } =
    useMutualFollowerSearch(debouncedUserSearch, { enabled: !!song });
  const mutualFollowers = suggestedUsers; // users who are both followers and following
  const isSearchingUsers = mutualFollowersQuery.isFetching;
  const isInitialLoading = mutualFollowersQuery.isLoading;
  const hasNextPage = mutualFollowersQuery.hasNextPage;
  const fetchNextPage = mutualFollowersQuery.fetchNextPage;
  const isError = mutualFollowersQuery.isError;

  // Ref for infinite scroll - intersection observer target
  const loadMoreRef = useRef<HTMLDivElement>(null);

  // Ref to track if component is mounted - prevents state updates after unmount
  const isMountedRef = useRef(true);

  useEffect(() => {
    isMountedRef.current = true;
    return () => {
      isMountedRef.current = false;
    };
  }, []);

  const incrementShareCount = useCallback(
    (clipId: string, sharePlatform: string) => {
      apiClient.POST('/api/gen/{gen_id}/increment_action_count/', {
        params: { path: { gen_id: clipId } },
        body: {
          action: 'share',
          share_platform: sharePlatform,
        },
      });
    },
    [apiClient]
  );

  const getShareUrl = useCallback(
    async (sharePlatform?: string): Promise<string> => {
      if (song) {
        const shareLink = await getShareLink({
          apiClient,
          contentType: 'song',
          contentId: song.id,
          platform: sharePlatform,
        });
        return shareLink || '';
      }
      return '';
    },
    [song, apiClient]
  );

  useEffect(() => {
    if (song) {
      logWebUserEvent({
        actionName: 'ShareModalOpened',
        context: {
          clipId: song.id || '',
          source: modalSource,
          modalType: 'share_with_friends' as const,
        } as const,
      });
    }
  }, [song, modalSource]);

  const handleClose = useCallback(() => {
    if (song) {
      logWebUserEvent({
        actionName: 'ShareModalClosed',
        context: {
          clipId: song?.id || '',
          source: modalSource,
          modalType: 'share_with_friends' as const,
        } as const,
      });
    }
    closeModal(ModalTypes.SHARE_WITH_FRIENDS);
  }, [song, modalSource, closeModal]);

  useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        e.stopPropagation();
        handleClose();
      }
    };
    window.addEventListener('keydown', handleEscape, true);
    return () => window.removeEventListener('keydown', handleEscape, true);
  }, [handleClose]);

  // Keep dropdown open unless user has typed and cleared their search with no results
  useEffect(() => {
    // If user has typed something, only show dropdown if we have results or are loading
    if (userSearchInput.trim().length > 0) {
      setShowUserDropdown(true);
    }
    // If search is cleared and we have results, show dropdown
    else if (mutualFollowers.length > 0 || !isError) {
      setShowUserDropdown(true);
    }
  }, [userSearchInput, mutualFollowers.length, isError]);

  // Reset selected index when search results change
  useEffect(() => {
    setSelectedUserIndex(0);
  }, [mutualFollowers]);

  // Delay showing loading message to prevent flicker for fast operations
  useEffect(() => {
    if (isInitialLoading) {
      // Set a timeout to show loading message after 500ms
      const timer = setTimeout(() => {
        setShowLoadingMessage(true);
      }, 300);

      return () => {
        clearTimeout(timer);
        setShowLoadingMessage(false);
      };
    } else {
      // Reset immediately when loading completes
      setShowLoadingMessage(false);
    }
  }, [isInitialLoading]);

  // Infinite scroll using IntersectionObserver for better performance
  useEffect(() => {
    const target = loadMoreRef.current;
    if (!target) return;

    const observer = new IntersectionObserver(
      (entries) => {
        const [entry] = entries;
        if (entry.isIntersecting && hasNextPage && !isSearchingUsers) {
          fetchNextPage();
        }
      },
      {
        root: null,
        rootMargin: '50px',
        threshold: 0.1,
      }
    );

    observer.observe(target);
    return () => {
      observer.disconnect();
    };
  }, [hasNextPage, isSearchingUsers, fetchNextPage]);

  const handleShareWithUser = useCallback(
    async (user: {
      handle?: string | null;
      displayName?: string | null;
      avatarImageUrl?: string | null;
    }) => {
      // Early validation - prevent race conditions by checking all prerequisites
      if (!song?.id) {
        console.error('Share failed: No song available');
        return;
      }

      // Type guard: ensure handle exists and is non-null
      if (!user.handle || typeof user.handle !== 'string') {
        toast({
          title: 'Share failed',
          description: 'Invalid user handle',
          status: 'error',
          duration: 2000,
          isClosable: true,
        });
        return;
      }

      // Prevent multiple simultaneous share attempts
      if (isSharingWithUser) {
        return;
      }

      // Store user handle for consistent reference throughout async operations
      const recipientHandle = user.handle;

      setIsSharingWithUser(true);

      let shareUrl: string | null = null;
      let shareId: string | null = null;

      try {
        // Step 1: Generate share URL
        shareUrl = await getShareUrl('in_app');

        // Check if component is still mounted after async operation
        if (!isMountedRef.current) return;

        if (!shareUrl) {
          throw new Error('Failed to generate share URL');
        }

        // Step 2: Extract share ID from URL
        try {
          const url = new URL(shareUrl);
          shareId = url.pathname.split('/').pop() || null;
        } catch (urlError) {
          console.error('Invalid share URL format:', shareUrl, urlError);
          throw new Error('Invalid share URL format');
        }

        if (!shareId) {
          throw new Error('Could not extract share ID from URL');
        }

        // Step 3: Create share event with atomicity check
        const response = await apiClient.POST('/api/share/event', {
          body: {
            share_id: shareId,
            recipient: recipientHandle,
            send_notification: true,
          },
        });

        // Check if component is still mounted after async operation
        if (!isMountedRef.current) return;

        // Step 4: Handle response
        if (response.data?.success) {
          // Success path - all operations completed atomically
          toast({
            title: 'Shared successfully!',
            description: `Shared with @${recipientHandle}`,
            status: 'success',
            duration: 3000,
            isClosable: true,
          });

          // Log analytics events (fire-and-forget, non-blocking)
          try {
            logWebUserEvent({
              actionName: 'ShareModalShareClicked',
              context: {
                clipId: song.id,
                source: modalSource,
                platformName: 'in_app',
                modalType: 'share_with_friends' as const,
              } as const,
            });

            eventLogger.logAudioActionEvent(
              true,
              ActionName.shareSongWithInApp,
              song,
              session,
              pathname
            );

            incrementShareCount(song.id, 'in_app');
          } catch (analyticsError) {
            // Don't let analytics failures affect user experience
            console.error('Analytics logging failed:', analyticsError);
          }

          // Reset UI state atomically (only if still mounted)
          if (isMountedRef.current) {
            setUserSearchInput('');
            setShowUserDropdown(false);
            setIsSharingWithUser(false);
          }

          // Close modal after successful share
          closeModal(ModalTypes.SHARE_WITH_FRIENDS);
        } else {
          // API returned non-success - share was not created
          const errorMessage =
            response.data?.message || 'Unable to share with this user';
          throw new Error(errorMessage);
        }
      } catch (error) {
        // Centralized error handling - ensures consistent state on any failure
        console.error('Share operation failed:', {
          error,
          song: song.id,
          recipient: recipientHandle,
          shareUrl,
          shareId,
        });

        const errorMessage =
          error instanceof Error
            ? error.message
            : 'An error occurred while sharing';

        toast({
          title: 'Share failed',
          description: errorMessage,
          status: 'error',
          duration: 3000,
          isClosable: true,
        });

        // Reset sharing state but keep modal open for retry (only if still mounted)
        if (isMountedRef.current) {
          setIsSharingWithUser(false);
        }
      }
    },
    [
      song,
      isSharingWithUser,
      getShareUrl,
      apiClient,
      modalSource,
      session,
      pathname,
      incrementShareCount,
      closeModal,
    ]
  );

  // Scroll selected item into view when navigating with keyboard
  useEffect(() => {
    if (
      selectedUserIndex >= 0 &&
      selectedUserIndex < userItemRefs.current.length
    ) {
      userItemRefs.current[selectedUserIndex]?.scrollIntoView({
        block: 'nearest',
        behavior: 'smooth',
      });
    }
  }, [selectedUserIndex]);

  // Keyboard navigation handler
  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
      if (!showUserDropdown || mutualFollowers.length === 0) return;

      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault();
          setSelectedUserIndex((prev) =>
            prev < mutualFollowers.length - 1 ? prev + 1 : prev
          );
          break;
        case 'ArrowUp':
          e.preventDefault();
          setSelectedUserIndex((prev) => (prev > 0 ? prev - 1 : prev));
          break;
        case 'Enter':
          e.preventDefault();
          if (
            selectedUserIndex >= 0 &&
            selectedUserIndex < mutualFollowers.length &&
            !isSharingWithUser
          ) {
            handleShareWithUser(mutualFollowers[selectedUserIndex]);
          }
          break;
        case 'Escape':
          e.preventDefault();
          setShowUserDropdown(false);
          break;
        case 'Tab':
          // Allow default tab behavior but close dropdown
          setShowUserDropdown(false);
          break;
      }
    },
    [
      showUserDropdown,
      mutualFollowers,
      selectedUserIndex,
      isSharingWithUser,
      handleShareWithUser,
    ]
  );

  // Focus the input when the modal opens
  useEffect(() => {
    if (userInputRef.current) {
      userInputRef.current.focus();
    }
  }, []);

  // Don't render if feature is not enabled or no song
  if (!showInAppSharing || !song) {
    return null;
  }

  return (
    <Modal
      title='Share with friends'
      titleClassName='text-2xl font-sans font-semibold pt-4 flex-1 text-center'
      closeButtonClasses='absolute right-4 top-4 w-12 h-12'
      onClose={handleClose}
      className='overflow-auto'
      contentWrapperClasses='w-[90%]'
      wrapperClasses='-mx-6'
      width={600}
    >
      <div className='flex flex-col p-8'>
        <div className='mx-auto flex w-full max-w-[500px] flex-1 flex-col items-stretch gap-6 px-4'>
          <div className='flex w-full flex-col gap-4'>
            <TextareaV2
              ref={userInputRef}
              value={userSearchInput}
              onChange={(e) => setUserSearchInput(e.target.value)}
              onKeyDown={handleKeyDown}
              placeholder='Search for mutual followers...'
              className='w-full rounded-2xl border-border-primary bg-background-primary'
              textAreaClassName='font-sans text-sm placeholder-foreground-inactive px-6 py-4'
              disabled={isSharingWithUser}
              minRows={1}
              maxRows={1}
              aria-label='Search for users to share with'
              aria-autocomplete='list'
              aria-controls={
                showUserDropdown ? 'user-search-dropdown' : undefined
              }
              aria-expanded={showUserDropdown}
              aria-activedescendant={
                showUserDropdown && mutualFollowers.length > 0
                  ? `user-item-${selectedUserIndex}`
                  : undefined
              }
              role='combobox'
            />
            {showUserDropdown && (
              <div
                id='user-search-dropdown'
                role='listbox'
                aria-label='User search results'
                className='w-full'
              >
                {/* Aria-live region for screen readers */}
                <div className='sr-only' aria-live='polite' aria-atomic='true'>
                  {showLoadingMessage &&
                    isInitialLoading &&
                    (userSearchInput.trim()
                      ? 'Searching for mutual followers'
                      : 'Loading your mutual followers')}
                  {isError && 'Error loading mutual followers'}
                  {!isInitialLoading &&
                    mutualFollowers.length > 0 &&
                    `Found ${mutualFollowers.length} mutual followers`}
                  {!isInitialLoading &&
                    mutualFollowers.length === 0 &&
                    'No mutual followers found'}
                </div>

                {isInitialLoading && !showLoadingMessage ? (
                  // Don't show anything for the first 500ms to prevent flicker
                  <div className='px-2 py-4'>&nbsp;</div>
                ) : isInitialLoading && showLoadingMessage ? (
                  <div className='px-2 py-4 text-center text-sm text-foreground-inactive'>
                    {userSearchInput.trim()
                      ? 'Searching...'
                      : 'Loading your mutual followers...'}
                  </div>
                ) : isError ? (
                  <div className='px-2 py-4 text-center text-sm text-accent-error-on-primary'>
                    Error loading mutual followers. Please try again.
                  </div>
                ) : mutualFollowers.length > 0 ? (
                  <div className='scrollbar-hide max-h-96 overflow-y-auto px-2 py-4'>
                    {userSearchInput.trim().length > 0 ? (
                      // Horizontal list layout when searching
                      <div className='flex flex-col'>
                        {mutualFollowers.map((user, index) => (
                          <button
                            key={user.handle}
                            ref={(el) => {
                              userItemRefs.current[index] = el;
                            }}
                            id={`user-item-${index}`}
                            onClick={() => handleShareWithUser(user)}
                            onMouseEnter={() => setSelectedUserIndex(index)}
                            disabled={isSharingWithUser}
                            role='option'
                            aria-selected={selectedUserIndex === index}
                            className={clsx(
                              'flex items-center gap-3 rounded-xl p-3',
                              'hover:bg-background-secondary',
                              'transition-colors',
                              'scroll-my-4',
                              {
                                'cursor-not-allowed opacity-50':
                                  isSharingWithUser,
                                'bg-background-tertiary ring-2 ring-border-primary':
                                  selectedUserIndex === index,
                              }
                            )}
                          >
                            <Avatar
                              src={user.avatarImageUrl}
                              displayName={
                                user.displayName || `@${user.handle}`
                              }
                              handle={user.handle || undefined}
                              size={40}
                              imageSize={ImageSize.SMALL}
                              className='h-10 w-10'
                            />
                            <div className='min-w-0 flex-1 text-left'>
                              <div className='truncate font-sans text-sm font-semibold'>
                                {user.displayName}
                              </div>
                              <div className='truncate font-sans text-xs text-foreground-inactive'>
                                @{user.handle}
                              </div>
                            </div>
                          </button>
                        ))}
                      </div>
                    ) : (
                      // Grid layout when not searching
                      <div className='grid grid-cols-3 gap-2 md:gap-4'>
                        {mutualFollowers.map((user, index) => (
                          <button
                            key={user.handle}
                            ref={(el) => {
                              userItemRefs.current[index] = el;
                            }}
                            id={`user-item-${index}`}
                            onClick={() => handleShareWithUser(user)}
                            onMouseEnter={() => setSelectedUserIndex(index)}
                            disabled={isSharingWithUser}
                            role='option'
                            aria-selected={selectedUserIndex === index}
                            className={clsx(
                              'flex flex-col items-center gap-1.5 rounded-xl p-2 md:gap-2 md:p-3',
                              'hover:bg-background-secondary',
                              'transition-colors',
                              'scroll-my-4',
                              {
                                'cursor-not-allowed opacity-50':
                                  isSharingWithUser,
                                'bg-background-tertiary ring-2 ring-border-primary':
                                  selectedUserIndex === index,
                              }
                            )}
                          >
                            <Avatar
                              src={user.avatarImageUrl}
                              displayName={
                                user.displayName || `@${user.handle}`
                              }
                              handle={user.handle || undefined}
                              size={64}
                              imageSize={ImageSize.SMALL}
                              className='h-12 w-12 md:h-16 md:w-16'
                            />
                            <div className='w-full text-center'>
                              <div className='truncate font-sans text-xs font-semibold md:text-sm'>
                                {user.displayName}
                              </div>
                              <div className='truncate font-sans text-[10px] text-foreground-inactive md:text-xs'>
                                @{user.handle}
                              </div>
                            </div>
                          </button>
                        ))}
                      </div>
                    )}
                    {/* Intersection observer target for infinite scroll */}
                    {hasNextPage && <div ref={loadMoreRef} className='h-1' />}
                    {/* Loading indicator when fetching more */}
                    {isSearchingUsers && !isInitialLoading && (
                      <div className='px-2 py-4 text-center text-sm text-foreground-inactive'>
                        Loading more...
                      </div>
                    )}
                  </div>
                ) : (
                  <div className='px-2 py-4 text-center text-sm text-foreground-inactive'>
                    No mutual followers found
                  </div>
                )}
              </div>
            )}
          </div>
          <div className='text-center text-sm text-foreground-inactive'>
            Search and share songs with people who follow you and you follow
            back
          </div>
        </div>
      </div>
    </Modal>
  );
};

export default ShareWithFriendsModal;
