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

/* eslint jsx-a11y/no-static-element-interactions: warn */
import { useOutsideClick } from '@chakra-ui/react';
import styled from '@emotion/styled';
import { noop } from 'lodash-es';
import { observer } from 'mobx-react-lite';
import {
  Dispatch,
  SetStateAction,
  memo,
  useEffect,
  useRef,
  useState,
} from 'react';
import ReactDOM from 'react-dom';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { useProjectSearch } from '@/components/clipBrowser/useProjectSearch';
import { useContextSelector } from '@/hooks/useContextSelector';
import useDebounceCallback from '@/hooks/useDebounceCallback';
import { FolderIcon, MusicNoteIcon } from '@/icons';
import { ProjectMetadataSchema } from '@/state/projectStore';

import CreateFormContext from '../../v2/CreateFormContext';
import { CreateModes } from '../../v2/types';
import CreateCard from './CreateCard';
import { bigSpace } from './themes';

const ContentWrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 1px;
  color: var(--color-foreground-primary);
`;

const RowWrapper = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 ${bigSpace}px;
  height: 56px;
  background: var(--color-background-fog-thin);
`;

const WorkspaceDropdown = observer(
  ({
    selectedProjectId,
    onSelectProject,
  }: {
    selectedProjectId: string | null;
    onSelectProject: (project: ProjectMetadataSchema) => void;
  }) => {
    const { project: projectStore } = useStores();
    const [open, setOpen] = useState(false);
    const [query, setQuery] = useState('');
    const [localQuery, setLocalQuery] = useState('');
    const [topPosition, setTopPosition] = useState(0);
    const [leftPosition, setLeftPosition] = useState(0);
    const [projects, setProjects] = useState<ProjectMetadataSchema[]>([]);

    const buttonRef = useRef<HTMLButtonElement>(null);
    const menuRef = useRef<HTMLDivElement | null>(null);

    const selectedProject = selectedProjectId
      ? projectStore.projectsById[selectedProjectId]
      : projectStore.projectsById[projectStore.currentProjectId];
    const displayName = selectedProjectId
      ? selectedProject?.name || 'Unknown Workspace'
      : 'My Workspace';

    useOutsideClick({
      ref: menuRef as React.RefObject<HTMLDivElement>,
      handler: (e) => {
        if (
          e.target &&
          !buttonRef.current?.contains(e.target as Node) &&
          open
        ) {
          setOpen(false);
          setQuery('');
        }
      },
    });

    useEffect(() => {
      const fetchProjects = async () => {
        await projectStore.fetchProjectsList();
        setProjects(projectStore.allProjects);
      };
      fetchProjects();
    }, []);

    const searchProjects = useProjectSearch();
    const debouncedSetSearchText = useDebounceCallback(
      (value: string) => setQuery(value),
      150
    );
    useEffect(() => {
      const fetchData = async (query: string) => {
        const fetchedProjects = await searchProjects(query);
        setProjects(fetchedProjects.projects ?? []);
      };
      fetchData(query);
    }, [query]);

    useEffect(() => {
      if (buttonRef.current) {
        const rect = buttonRef.current.getBoundingClientRect();
        const scrollX = window.scrollX;
        const scrollY = window.scrollY;

        const menuHeight = 240;
        const buttonLeft = rect.left + scrollX;
        const buttonTop = rect.top + scrollY;
        const buttonWidth = rect.width;

        setTopPosition(buttonTop - menuHeight);

        const dropdownWidth = 260;
        let leftPos = buttonLeft - dropdownWidth + buttonWidth;

        if (leftPos < 0) {
          leftPos = 0;
        }

        const viewportWidth = window.innerWidth;
        if (leftPos + dropdownWidth > viewportWidth) {
          leftPos = viewportWidth - dropdownWidth;
        }

        setLeftPosition(leftPos);
      }
    }, [open]);

    return (
      <>
        <Button
          ref={buttonRef}
          shape={ButtonShape.Pill}
          size={ButtonSize.Small}
          variant={ButtonVariant.Standard}
          className='text-xs leading-[24px]'
          aria-label={`${open ? 'Close' : 'Open'} workspace dropdown`}
          onClick={() => setOpen((prev) => !prev)}
        >
          {displayName}
        </Button>

        {open &&
          ReactDOM.createPortal(
            <div
              className='absolute z-1500 flex h-auto max-h-[240px] min-h-[240px] w-[260px] flex-col gap-3 rounded-lg border border-white/5 bg-background-secondary p-3 shadow-lg'
              style={{
                top: topPosition,
                left: leftPosition,
              }}
              ref={menuRef}
            >
              <input
                type='text'
                className='rounded-lg bg-background-primary p-2 pl-4 outline-none'
                placeholder='Search...'
                value={localQuery}
                onChange={(e) => {
                  setLocalQuery(e.target.value);
                  debouncedSetSearchText(e.target.value);
                }}
              />
              <div className='flex-1 overflow-y-auto text-center'>
                {projects.length === 0 ? (
                  <span className='text-sm text-foreground-secondary'>
                    No workspaces
                  </span>
                ) : null}
                {projects
                  .filter(
                    (p: ProjectMetadataSchema) =>
                      query.length === 0 ||
                      p.name.toLowerCase().includes(query.toLowerCase())
                  )
                  .map((p: ProjectMetadataSchema) => (
                    <div
                      className='flex h-auto w-full cursor-pointer flex-row rounded-md p-2 hover:bg-background-fog-thick'
                      key={p.id}
                      onClick={() => {
                        onSelectProject(p);
                        setOpen(false);
                        setQuery('');
                      }}
                    >
                      <span>
                        {p.name} ({p.clip_count} clips)
                      </span>
                    </div>
                  ))}
              </div>
            </div>,
            document.body
          )}
      </>
    );
  }
);

const TitleWorkspaceCard = memo(
  observer(function TitleWorkspaceCard({
    title,
    setTitle,
  }: {
    title: string;
    setTitle: Dispatch<SetStateAction<string>>;
  }) {
    const { project: projectStore } = useStores();

    return (
      <CreateCard transparentBackground>
        <ContentWrapper>
          {setTitle !== noop && (
            <RowWrapper>
              <MusicNoteIcon className='h-5 w-5' />
              <input
                className='ml-2 flex-1 bg-transparent py-2 outline-none placeholder:text-background-fog-dense'
                value={title}
                onChange={(e) => setTitle(e.target.value)}
                placeholder='Song Title (Optional)'
              />
            </RowWrapper>
          )}
          <RowWrapper>
            <span className='flex items-center gap-2'>
              <FolderIcon className='h-5 w-5' />
              Save to...
            </span>
            <WorkspaceDropdown
              selectedProjectId={projectStore.userSelectedProjectId}
              onSelectProject={(selectedProject: ProjectMetadataSchema) => {
                projectStore.setUserSelectedProjectId(
                  selectedProject.id,
                  selectedProject.name
                );
              }}
            />
          </RowWrapper>
        </ContentWrapper>
      </CreateCard>
    );
  })
);

const FALLBACK_TITLE = ['', noop] as const;

export const CustomTitleWorkspaceCard = () => {
  const [title, setTitle] = useContextSelector(CreateFormContext, (context) => {
    return context.state.global.mode === CreateModes.CUSTOM
      ? context.selectState<string>([CreateModes.CUSTOM, 'title'])
      : FALLBACK_TITLE;
  });

  return <TitleWorkspaceCard title={title} setTitle={setTitle} />;
};

export default TitleWorkspaceCard;
