'use client';

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

/* eslint jsx-a11y/no-static-element-interactions: warn */
import {
  Accordion,
  AccordionButton,
  AccordionIcon,
  AccordionItem,
  AccordionPanel,
} from '@chakra-ui/react';
import { observer } from 'mobx-react-lite';
import { useCallback, useEffect, useRef, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import Link from '@/components/link/Link';
import { DesktopOnly, MobileOnly } from '@/components/responsive/Responsive';
import { SongMenuWithContext } from '@/components/song/newActions/SongMenuWithContext';
import { ChevronDownIcon, ChevronUpIcon } from '@/icons';
import { ContextType } from '@/logging/contextTypes';
import { Clip } from '@/state/clipStore';
import { getClipDisplayTags, getClipTitle } from '@/utils/clip';
import { NO_STYLE_FALLBACK } from '@/utils/constants';

import ImageWithFallback from '../image/ImageWithFallback';
import SongCardAlt from '../song/SongCardAlt';
import SpinnerSVG from '../svg/SpinnerSVG';
import MusicStyleTags from '../tag/MusicStyleTags';
import { tagsToArray, tagsToNegativeTags } from './songUtils';

interface RemixesProps {
  clip: Clip;
  containerHeight?: number;
  hideToggle?: boolean;
  useGradientBackground?: boolean;
}

const Remixes = observer(
  ({
    clip,
    containerHeight = 300,
    hideToggle = false,
    useGradientBackground = false,
  }: RemixesProps) => {
    const { clips, playbar, queue, session } = useStores();
    const [showChildren, setShowChildren] = useState(false);
    const [childrenPage, setChildrenPage] = useState(1);
    const [isLoadingMore, setIsLoadingMore] = useState(false);
    const [remixCount, setRemixCount] = useState<number>(0);
    const [isRemixesPanelOpen, setIsRemixesPanelOpen] = useState(false);
    const [userGroups, setUserGroups] = useState<any[]>([]);
    const [expandedUsers, setExpandedUsers] = useState<Set<string>>(new Set());
    const [userRemixesCache, setUserRemixesCache] = useState<
      Record<string, any>
    >({});
    const remixesContainerRef = useRef<HTMLDivElement>(null);
    const [isClosing, setIsClosing] = useState(false);

    const tags = [
      ...tagsToArray(getClipDisplayTags(clip)),
      ...tagsToNegativeTags(tagsToArray(clip.metadata?.negative_tags || '')),
    ];

    useEffect(() => {
      const resetState = () => {
        setIsClosing(false);
        setShowChildren(false);
        setChildrenPage(1);
        setIsRemixesPanelOpen(false);
      };

      resetState();

      const timeoutId = setTimeout(() => {
        if (remixesContainerRef.current) {
          remixesContainerRef.current.scrollTop = 0;
        }
      }, 50);

      return () => clearTimeout(timeoutId);
    }, [clip.id]);

    useEffect(() => {
      const fetchRemixCount = async () => {
        const count = session?.flags?.['clip-parent-populates-remix-sidebar']
          ? await clips.getDisplayableRemixesCount(clip.id)
          : await clips.getDirectChildrenCount(clip.id);
        setRemixCount(count);
      };

      fetchRemixCount();
    }, [clip.id, clips, session?.flags]);

    useEffect(() => {
      if (remixCount > 0) {
        const loadRemixesByUser = async () => {
          setIsLoadingMore(true);
          try {
            const result = session?.flags?.[
              'clip-parent-populates-remix-sidebar'
            ]
              ? await clips.getDisplayableRemixesByUser(clip.id, childrenPage)
              : await clips.getDirectChildrenByUser(clip.id, childrenPage);
            if (result && result.user_groups) {
              setUserGroups(result.user_groups);
              setRemixCount(result.total_count || 0);
            }
          } finally {
            setIsLoadingMore(false);
          }
        };

        loadRemixesByUser();
      }
    }, [clip.id, remixCount, clips, childrenPage, session?.flags]);

    const toggleUserExpand = async (userId: string) => {
      const newExpandedUsers = new Set(expandedUsers);

      if (expandedUsers.has(userId)) {
        newExpandedUsers.delete(userId);
      } else {
        newExpandedUsers.add(userId);

        // Only fetch if not already in cache
        if (!userRemixesCache[userId]) {
          const userRemixes = session?.flags?.[
            'clip-parent-populates-remix-sidebar'
          ]
            ? await clips.getDisplayableUserRemixesForClip(clip.id, userId)
            : await clips.getUserRemixesForClip(clip.id, userId);
          if (userRemixes) {
            setUserRemixesCache((prev) => ({
              ...prev,
              [userId]: userRemixes,
            }));
          }
        }
      }

      setExpandedUsers(newExpandedUsers);
    };

    const handlePlayClip = (clipToPlay: Clip) => {
      const remixClips = clips.directChildrenByClipId[clip.id]?.clips || [];

      const clipIndex = remixClips.findIndex((c) => c.id === clipToPlay.id);

      if (clipIndex !== -1) {
        queue.setPlayContext({
          contextType: ContextType.SongRecommendationsRemixes,
          contextId: clip.id,
          currentIndex: clipIndex + 1,
          clips: [clip, ...remixClips],
          pendingClips: [],
        });
      }

      playbar.playClip(clipToPlay);
    };

    useEffect(() => {
      if (hideToggle) {
        setShowChildren(true);
        setIsRemixesPanelOpen(true);

        const loadRemixes = async () => {
          setIsLoadingMore(true);
          try {
            if (session?.flags?.['clip-parent-populates-remix-sidebar']) {
              await clips.getDisplayableRemixes(clip.id, 1);
            } else {
              await clips.getDirectChildren(clip.id, 1);
            }
            setChildrenPage(1);
          } finally {
            setIsLoadingMore(false);
          }
        };

        loadRemixes();
      }
    }, [hideToggle, clip.id, clips, session?.flags]);

    const heightAdjustment = 180;

    const remixText = remixCount === 1 ? 'Remix' : 'Remixes';

    const handleScroll = (e: Event) => {
      const target = e.target as HTMLDivElement;
      if (
        target.scrollHeight - target.scrollTop <= target.clientHeight + 100 &&
        !isLoadingMore
      ) {
        setChildrenPage((prevPage) => prevPage + 1);
      }
    };

    const toggleRemixesPanel = useCallback(() => {
      if (showChildren) {
        setIsClosing(true);
        setTimeout(() => {
          setShowChildren(false);
          setIsClosing(false);
        }, 100);
      } else {
        setShowChildren(true);

        const loadRemixes = async () => {
          setIsLoadingMore(true);
          try {
            if (session?.flags?.['clip-parent-populates-remix-sidebar']) {
              await clips.getDisplayableRemixesByUser(clip.id, 1);
            } else {
              await clips.getDirectChildrenByUser(clip.id, 1);
            }
            setChildrenPage(1);
          } finally {
            setIsLoadingMore(false);
          }
        };

        loadRemixes();
      }
    }, [showChildren, clip.id, clips, session?.flags]);

    if (remixCount === 0) {
      return null;
    }

    const renderUserRemixGroup = (group: any) => {
      const isExpanded = expandedUsers.has(group.user_id);
      const userRemixes = userRemixesCache[group.user_id];

      const firstRemixWithUser = {
        ...group.first_remix,
        display_name: group.user_display_name,
        handle: group.user_handle,
        avatar_image_url: group.user_avatar_image_url,
      };

      return (
        <div key={group.user_id} className='mb-2'>
          <SongCardAlt
            key={group.first_remix.id}
            clip={firstRemixWithUser}
            onClick={() => handlePlayClip(group.first_remix)}
            showActions={true}
            transparent={true}
            withTitleLink={true}
            withStyleLinks={true}
            bgColor='transparent'
          />

          {group.remix_count > 1 && (
            <>
              {isExpanded &&
              userRemixes &&
              userRemixes.remixes &&
              userRemixes.remixes.length > 1 ? (
                <div className='mt-1'>
                  <div
                    className='overflow-hidden rounded-lg bg-black/30 backdrop-blur-md'
                    style={{ animation: 'slideDown 0.3s ease-out' }}
                  >
                    <div
                      className='flex w-auto cursor-pointer items-center justify-center gap-1 px-4 py-2 text-xs text-primary/70 hover:text-primary'
                      onClick={() => toggleUserExpand(group.user_id)}
                      style={{ position: 'relative', height: '36px' }}
                    >
                      <ChevronUpIcon className='h-3 w-3' />
                      <span>
                        {group.remix_count - 1} more{' '}
                        {group.remix_count - 1 === 1 ? 'remix' : 'remixes'}
                      </span>
                    </div>
                    <div className='space-y-1 p-3 pt-0'>
                      {userRemixes.remixes.slice(1).map((remix: Clip) => (
                        <SongCardAlt
                          key={remix.id}
                          clip={remix}
                          onClick={() => handlePlayClip(remix)}
                          showActions={true}
                          transparent={true}
                          withTitleLink={true}
                          withStyleLinks={true}
                          bgColor='transparent'
                        />
                      ))}
                    </div>
                  </div>
                </div>
              ) : (
                <div
                  className='mt-1 flex w-auto cursor-pointer items-center justify-center gap-1 rounded-lg bg-black/30 px-4 py-2 text-xs text-primary/70 backdrop-blur-md transition-colors hover:bg-black/40 hover:text-primary'
                  onClick={() => toggleUserExpand(group.user_id)}
                  style={{ position: 'relative', height: '36px' }}
                >
                  <ChevronDownIcon className='h-3 w-3' />
                  <span>
                    {group.remix_count - 1} more{' '}
                    {group.remix_count - 1 === 1 ? 'remix' : 'remixes'}
                  </span>
                </div>
              )}
            </>
          )}
        </div>
      );
    };

    return (
      <>
        {/* Mobile accordion view */}
        <MobileOnly>
          <div className='-mx-6 mt-8 mb-20'>
            <Accordion
              allowToggle
              className='mx-4'
              onChange={(expandedIndex) => {
                if (expandedIndex === 0 && !isRemixesPanelOpen) {
                  setIsRemixesPanelOpen(true);
                  setShowChildren(true);
                } else if (expandedIndex !== 0 && isRemixesPanelOpen) {
                  setIsRemixesPanelOpen(false);
                  setShowChildren(false);
                }
              }}
            >
              <AccordionItem border='none'>
                <AccordionButton className='flex justify-between py-4 font-mono text-xs text-primary uppercase'>
                  {remixCount} {remixText} of this song
                  <AccordionIcon />
                </AccordionButton>
                <AccordionPanel
                  pb={4}
                  className='rounded-b-lg bg-background-primary'
                >
                  {isLoadingMore ? (
                    <SpinnerSVG />
                  ) : userGroups.length > 0 ? (
                    <div className='space-y-1 px-2'>
                      {userGroups.map((group) => renderUserRemixGroup(group))}
                    </div>
                  ) : (
                    <div className='py-4 text-center text-primary/50'>
                      No remixes found. Please try refreshing the page.
                    </div>
                  )}
                </AccordionPanel>
              </AccordionItem>
            </Accordion>
          </div>
        </MobileOnly>

        {/* Desktop view */}
        <DesktopOnly>
          <div
            className={`relative ${hideToggle ? 'px-0' : 'px-4'}`}
            onClick={(e) => e.stopPropagation()}
          >
            {!hideToggle && (
              <div className='flex w-full flex-col gap-2 bg-background-primary'>
                {!showChildren && (
                  <button
                    onClick={toggleRemixesPanel}
                    className='flex items-center justify-center gap-2 py-2 font-mono text-[10px] text-primary uppercase'
                    style={{
                      display: 'flex',
                      alignItems: 'center',
                    }}
                  >
                    <span>
                      {remixCount} {remixText} of this song
                    </span>
                    <span>
                      <ChevronUpIcon className='h-3 w-3 text-primary' />
                    </span>
                  </button>
                )}

                {showChildren && !isClosing && (
                  <div className='-mx-4 mb-2 flex flex-col border-t border-b border-white/40 bg-background-primary'>
                    <div className='flex items-center gap-3 p-3'>
                      <div className='h-12 w-8 shrink-0 overflow-hidden rounded'>
                        <ImageWithFallback
                          src={clip.image_url}
                          alt={'Current song thumbnail'}
                          className='h-full w-full object-cover'
                        />
                      </div>
                      <div className='flex min-w-0 flex-1 flex-col'>
                        <div className='flex items-start justify-between'>
                          <Link
                            href={`/song/${clip.id}`}
                            className='text-md truncate text-primary hover:underline'
                          >
                            {getClipTitle(clip)}
                          </Link>
                        </div>

                        <MusicStyleTags
                          className='line-clamp-1 font-sans text-xs break-normal break-words whitespace-pre-wrap text-primary/70'
                          tags={tags.length ? tags : [NO_STYLE_FALLBACK]}
                          title={clip.metadata.tags || ''}
                          renderTag={tags.length ? undefined : null}
                        />

                        <div className='mt-1 flex items-center gap-2'>
                          <div className='h-4 w-4 shrink-0 overflow-hidden rounded-full'>
                            <ImageWithFallback
                              src={clip.avatar_image_url}
                              alt={'User avatar'}
                              className='h-full w-full object-cover'
                            />
                          </div>
                          <Link
                            href={`/@${clip.handle}`}
                            className='truncate text-xs text-primary hover:underline'
                          >
                            {clip.display_name || clip.handle}
                          </Link>
                        </div>
                      </div>
                      <SongMenuWithContext clip={clip} />
                    </div>
                  </div>
                )}
              </div>
            )}

            {(showChildren || isClosing || hideToggle) && (
              <div
                ref={remixesContainerRef}
                className={`${hideToggle ? 'w-full' : 'absolute right-0 bottom-full left-0'} transform overflow-y-auto px-2 transition-all ${hideToggle ? '' : 'shadow-[inset_0_0_20px_rgba(0,0,0,0.3)] backdrop-blur-xl backdrop-saturate-110'}`}
                style={{
                  animation: hideToggle
                    ? undefined
                    : isClosing
                      ? 'slideDown 0.1s ease-out forwards'
                      : 'slideUp 0.2s ease-out forwards',
                  height: hideToggle
                    ? 'auto'
                    : `${containerHeight - heightAdjustment}px`,
                  maxHeight: hideToggle
                    ? undefined
                    : `${containerHeight - heightAdjustment}px`,
                  transform: hideToggle ? undefined : 'translateY(0)',
                  opacity: hideToggle ? 1 : undefined,
                  background:
                    hideToggle && !useGradientBackground
                      ? 'transparent'
                      : 'radial-gradient(circle at left top, rgb(110, 61, 34) 15%, rgb(72, 46, 23) 34%, rgb(68 33 51) 55%, rgb(24, 24, 25) 73%)',
                  backgroundSize: 'cover, cover',
                  backgroundPosition: 'center, center',
                  backgroundBlendMode: 'overlay',
                }}
                onClick={(e) => e.stopPropagation()}
                onScroll={(e) => {
                  e.stopPropagation();
                  handleScroll(e as unknown as Event);
                }}
              >
                <div className='relative h-full'>
                  <div className={`relative z-10 space-y-1 px-0 pb-4`}>
                    {!hideToggle && (
                      <div className='sticky top-0 z-20 w-full'>
                        <button
                          onClick={toggleRemixesPanel}
                          className='flex w-full items-center justify-center gap-2 py-2 font-mono text-[10px] text-primary uppercase'
                          style={{
                            background: 'transparent',
                          }}
                        >
                          <span>
                            {remixCount} {remixText} of this song
                          </span>
                          <ChevronDownIcon className='h-3 w-3 text-primary' />
                        </button>
                      </div>
                    )}

                    <div className='bg-transparent'>
                      {isLoadingMore ? (
                        <div className='py-4 text-center text-primary/50'>
                          Loading remixes...
                        </div>
                      ) : (
                        userGroups.map((group) => renderUserRemixGroup(group))
                      )}
                    </div>
                  </div>
                </div>
              </div>
            )}

            <style jsx global>{`
              @keyframes slideUp {
                from {
                  transform: translateY(20px);
                  opacity: 0;
                }
                to {
                  transform: translateY(0);
                  opacity: 1;
                }
              }

              @keyframes slideDown {
                from {
                  max-height: 0;
                  overflow: hidden;
                  opacity: 0.8;
                }
                to {
                  max-height: 500px;
                  overflow: hidden;
                  opacity: 1;
                }
              }
            `}</style>
          </div>
        </DesktopOnly>
      </>
    );
  }
);

export default Remixes;
