'use client';

/* eslint jsx-a11y/click-events-have-key-events: warn */

/* eslint jsx-a11y/no-static-element-interactions: warn */
import clsx from 'clsx';
import { useCallback, useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';

import { useStores } from '@/app/(root)/AppProviders';
import FeedItemList from '@/components/feed/FeedItemList';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import UserRow from '@/components/user/UserRow';
import type { components } from '@/lib/gen';

import Modal from './Modal';

interface FollowersFollowingModalProps {
  isOpen: boolean;
  onClose: () => void;
  profileHandle: string;
  initialTab?: 'followers' | 'following' | 'remixes-inspired';
}

const FollowersFollowingModal = ({
  isOpen,
  onClose,
  profileHandle,
  initialTab = 'followers',
}: FollowersFollowingModalProps) => {
  const { library, clips: clipsStore, session } = useStores();

  const [activeTab, setActiveTab] = useState<
    'followers' | 'following' | 'remixes-inspired'
  >(initialTab);
  const [followers, setFollowers] = useState<
    components['schemas']['SimpleProfileInfoSchema'][]
  >([]);
  const [following, setFollowing] = useState<
    components['schemas']['SimpleProfileInfoSchema'][]
  >([]);
  const [remixesInspired, setRemixesInspired] = useState<
    components['schemas']['GeneratedClipSchema'][]
  >([]);

  const [followersPage, setFollowersPage] = useState(1);
  const [followingPage, setFollowingPage] = useState(1);
  const [remixesPage, setRemixesPage] = useState(1);

  const [loadingFollowers, setLoadingFollowers] = useState(false);
  const [loadingFollowing, setLoadingFollowing] = useState(false);
  const [loadingRemixes, setLoadingRemixes] = useState(false);

  const [loadingMoreFollowers, setLoadingMoreFollowers] = useState(false);
  const [loadingMoreFollowing, setLoadingMoreFollowing] = useState(false);
  const [loadingMoreRemixes, setLoadingMoreRemixes] = useState(false);

  const [hasMoreFollowers, setHasMoreFollowers] = useState(true);
  const [hasMoreFollowing, setHasMoreFollowing] = useState(true);
  const [hasMoreRemixes, setHasMoreRemixes] = useState(true);

  const [followersLoaded, setFollowersLoaded] = useState(false);
  const [followingLoaded, setFollowingLoaded] = useState(false);
  const [remixesLoaded, setRemixesLoaded] = useState(false);

  useEffect(() => {
    setActiveTab(initialTab);
  }, [initialTab]);

  const fetchFollowers = useCallback(
    async (page = 1) => {
      if (page === 1) {
        setLoadingFollowers(true);
      } else {
        setLoadingMoreFollowers(true);
      }

      try {
        const { data } = await library.apiClient.GET(
          '/api/profiles/{handle}/followers',
          {
            params: {
              path: { handle: profileHandle },
              query: { page },
            },
          }
        );

        if (data) {
          if (page === 1) {
            setFollowers(data.profiles || []);
            setFollowersLoaded(true);
          } else {
            setFollowers((prev) => [...prev, ...(data.profiles || [])]);
          }
          setFollowersPage(page);
          setHasMoreFollowers(
            data.profiles.length > 0 &&
              data.num_total_profiles > 0 &&
              data.profiles.length < data.num_total_profiles
          );
        }
      } catch (error) {
        console.error('Error fetching followers:', error);
      } finally {
        setLoadingFollowers(false);
        setLoadingMoreFollowers(false);
      }
    },
    [library.apiClient, profileHandle]
  );

  const fetchFollowing = useCallback(
    async (page = 1) => {
      if (page === 1) {
        setLoadingFollowing(true);
      } else {
        setLoadingMoreFollowing(true);
      }

      try {
        const { data } = await library.apiClient.GET(
          '/api/profiles/{handle}/following',
          {
            params: {
              path: { handle: profileHandle },
              query: { page },
            },
          }
        );

        if (data) {
          if (page === 1) {
            setFollowing(data.profiles || []);
            setFollowingLoaded(true);
          } else {
            setFollowing((prev) => [...prev, ...(data.profiles || [])]);
          }
          setFollowingPage(page);
          setHasMoreFollowing(
            data.profiles.length > 0 &&
              data.num_total_profiles > 0 &&
              data.profiles.length < data.num_total_profiles
          );
        }
      } catch (error) {
        console.error('Error fetching following:', error);
      } finally {
        setLoadingFollowing(false);
        setLoadingMoreFollowing(false);
      }
    },
    [library.apiClient, profileHandle]
  );

  const fetchRemixesInspired = useCallback(
    async (page = 1) => {
      if (page === 1) {
        setLoadingRemixes(true);
      } else {
        setLoadingMoreRemixes(true);
      }

      try {
        const data = await clipsStore.getRemixesInspired(
          profileHandle,
          page,
          20
        );

        if (data) {
          if (page === 1) {
            setRemixesInspired(data.clips || []);
            setRemixesLoaded(true);
          } else {
            setRemixesInspired((prev) => [...prev, ...(data.clips || [])]);
          }
          setRemixesPage(page);

          const hasMore =
            data.current_page < data.total_pages ||
            (data.clips && data.clips.length === 20);
          setHasMoreRemixes(hasMore);
        }
      } catch (error) {
        console.error('Error fetching remixes inspired:', error);
      } finally {
        setLoadingRemixes(false);
        setLoadingMoreRemixes(false);
      }
    },
    [clipsStore, profileHandle]
  );

  const { ref: followersInfiniteRef } = useInView({
    threshold: 0,
    onChange: (inView) => {
      if (
        inView &&
        activeTab === 'followers' &&
        hasMoreFollowers &&
        !loadingMoreFollowers
      ) {
        fetchFollowers(followersPage + 1);
      }
    },
  });

  const { ref: followingInfiniteRef } = useInView({
    threshold: 0,
    onChange: (inView) => {
      if (
        inView &&
        activeTab === 'following' &&
        hasMoreFollowing &&
        !loadingMoreFollowing
      ) {
        fetchFollowing(followingPage + 1);
      }
    },
  });

  const { ref: remixesInfiniteRef } = useInView({
    threshold: 0,
    onChange: (inView) => {
      if (
        inView &&
        activeTab === 'remixes-inspired' &&
        hasMoreRemixes &&
        !loadingMoreRemixes
      ) {
        fetchRemixesInspired(remixesPage + 1);
      }
    },
  });

  useEffect(() => {
    if (isOpen) {
      setFollowers([]);
      setFollowing([]);
      setRemixesInspired([]);
      setFollowersPage(1);
      setFollowingPage(1);
      setRemixesPage(1);
      setHasMoreFollowers(true);
      setHasMoreFollowing(true);
      setHasMoreRemixes(true);
      setFollowersLoaded(false);
      setFollowingLoaded(false);
      setRemixesLoaded(false);
    }
  }, [isOpen]);

  useEffect(() => {
    if (isOpen) {
      if (activeTab === 'followers' && !followersLoaded) {
        fetchFollowers(1);
      } else if (activeTab === 'following' && !followingLoaded) {
        fetchFollowing(1);
      } else if (activeTab === 'remixes-inspired' && !remixesLoaded) {
        fetchRemixesInspired(1);
      }
    }
  }, [
    isOpen,
    activeTab,
    followersLoaded,
    followingLoaded,
    remixesLoaded,
    fetchFollowers,
    fetchFollowing,
    fetchRemixesInspired,
  ]);

  const renderUserList = (
    users: components['schemas']['SimpleProfileInfoSchema'][],
    loading: boolean,
    loadingMore: boolean,
    infiniteRef: any
  ) => {
    if (loading) {
      return (
        <div className='flex h-[64px] items-center justify-center py-4'>
          <SpinnerSVG />
        </div>
      );
    }

    if (users.length === 0) {
      return (
        <div className='flex items-center justify-center py-4'>
          <p className='text-foreground-secondary'>No {activeTab} yet.</p>
        </div>
      );
    }

    return (
      <div className='space-y-2'>
        {users.map((user) => (
          <UserRow
            key={user.user_id}
            user={user}
            hideFollowButton={
              !!session.userId &&
              user.external_user_id?.toString() === session.userId
            }
            onFollowToggle={async (userId, isFollowing) => {
              await library.apiClient.POST('/api/profiles/follow', {
                body: {
                  unfollow: !isFollowing,
                  handle: user.handle || '',
                },
              });

              const updatedUsers = users.map((u) =>
                u.user_id === userId ? { ...u, is_following: isFollowing } : u
              );
              if (activeTab === 'followers') {
                setFollowers(updatedUsers);
              } else {
                setFollowing(updatedUsers);
              }
            }}
          />
        ))}
        {hasMoreFollowers && activeTab === 'followers' && (
          <div
            ref={infiniteRef}
            className='flex w-full items-center justify-center py-4'
          >
            {loadingMore && <SpinnerSVG />}
          </div>
        )}
        {hasMoreFollowing && activeTab === 'following' && (
          <div
            ref={infiniteRef}
            className='flex w-full items-center justify-center py-4'
          >
            {loadingMore && <SpinnerSVG />}
          </div>
        )}
      </div>
    );
  };

  const renderRemixesList = () => {
    if (loadingRemixes) {
      return (
        <div className='flex h-[64px] items-center justify-center py-4'>
          <SpinnerSVG />
        </div>
      );
    }

    if (remixesInspired.length === 0) {
      return (
        <div className='flex h-[64px] items-center justify-center py-4'>
          <p className='text-foreground-secondary'>No remixes inspired yet.</p>
        </div>
      );
    }

    return (
      <div className='space-y-1'>
        <FeedItemList
          id={`remixes-inspired-${profileHandle}`}
          title=''
          hideAvatar={false}
          feedItems={remixesInspired.map((clip) => ({
            ...clip,
            entity_type: 'song_schema' as const,
          }))}
          index={0}
          contextId={profileHandle}
          className='min-h-0'
        />
        {hasMoreRemixes && (
          <div
            ref={remixesInfiniteRef}
            className='flex w-full items-center justify-center py-4'
          >
            {loadingMoreRemixes && <SpinnerSVG />}
          </div>
        )}
      </div>
    );
  };

  if (!isOpen) return null;

  return (
    <Modal
      onClose={onClose}
      title={`${profileHandle}'s circle`}
      titleClassName='text-[20px] font-normal font-sans font-medium pt-[10px] leading-[24px] max-w-[343px]'
      titleWrapperClasses='p-6 pb-0 relative z-10 block text-center'
      wrapperClasses='h-[calc(100%-90px)] overflow-hidden relative z-10'
      contentWrapperClasses='md:max-h-[600px] h-[calc(100%-90px)]'
      closeButtonClasses='absolute right-[10px] top-[10px] h-[40px] w-[40px] color-white z-20 overflow-hidden p-0 rounded-[100px] bg-none'
      withAuraBackground={false}
      disablePadding={true}
      withHorizontalPadding={true}
      disableOutsideClick={false}
    >
      <div className='relative z-10 flex h-full w-full flex-col px-[16px]'>
        <div className='mt-[12px] mb-0 flex cursor-pointer items-center justify-between'>
          <div
            className={clsx(
              'h-[40px] flex-1 text-center text-sm leading-[40px]',
              activeTab === 'followers' && 'border-b border-border-primary'
            )}
            onClick={() => setActiveTab('followers')}
          >
            Followers
          </div>
          <div
            className={clsx(
              'h-[40px] flex-1 text-center text-sm leading-[40px]',
              activeTab === 'following' && 'border-b border-border-primary'
            )}
            onClick={() => setActiveTab('following')}
          >
            Following
          </div>
          <div
            className={clsx(
              'h-[40px] flex-1 text-center text-sm leading-[40px]',
              activeTab === 'remixes-inspired' &&
                'border-b border-border-primary'
            )}
            onClick={() => setActiveTab('remixes-inspired')}
          >
            Remixes Inspired
          </div>
        </div>

        <div
          className='overflow-y-auto pb-[16px]'
          style={{ scrollbarWidth: 'none' }}
        >
          {activeTab === 'followers'
            ? renderUserList(
                followers,
                loadingFollowers,
                loadingMoreFollowers,
                followersInfiniteRef
              )
            : activeTab === 'following'
              ? renderUserList(
                  following,
                  loadingFollowing,
                  loadingMoreFollowing,
                  followingInfiniteRef
                )
              : renderRemixesList()}
        </div>
      </div>
    </Modal>
  );
};

export default FollowersFollowingModal;
