import type { IChartEvent } from '@openpanel/validation';
import { useQuery } from '@tanstack/react-query';
import { AnimatePresence, motion } from 'framer-motion';
import {
  ArrowLeftIcon,
  Building2Icon,
  DatabaseIcon,
  UserIcon,
} from 'lucide-react';
import VirtualList from 'rc-virtual-list';
import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { Input } from '@/components/ui/input';
import { useAppParams } from '@/hooks/use-app-params';
import { useEventProperties } from '@/hooks/use-event-properties';
import { useTRPC } from '@/integrations/trpc/react';

interface PropertiesComboboxProps {
  event?: IChartEvent;
  children: (setOpen: Dispatch<SetStateAction<boolean>>) => React.ReactNode;
  onSelect: (action: {
    value: string;
    label: string;
    description: string;
  }) => void;
  exclude?: string[];
  mode?: 'events' | 'profile';
}

function SearchHeader({
  onBack,
  onSearch,
  value,
}: {
  onBack?: () => void;
  onSearch: (value: string) => void;
  value: string;
}) {
  return (
    <div className="row items-center gap-1">
      {!!onBack && (
        <Button onClick={onBack} size="icon" variant="ghost">
          <ArrowLeftIcon className="size-4" />
        </Button>
      )}
      <Input
        autoFocus
        onChange={(e) => onSearch(e.target.value)}
        placeholder="Search"
        value={value}
      />
    </div>
  );
}

export function PropertiesCombobox({
  event,
  children,
  onSelect,
  mode,
  exclude = [],
}: PropertiesComboboxProps) {
  const { projectId } = useAppParams();
  const trpc = useTRPC();
  const [open, setOpen] = useState(false);
  const properties = useEventProperties({
    event: event?.name,
    projectId,
  });
  const groupPropertiesQuery = useQuery(
    trpc.group.properties.queryOptions({ projectId })
  );
  const [state, setState] = useState<'index' | 'event' | 'profile' | 'group'>(
    'index'
  );
  const [search, setSearch] = useState('');
  const [direction, setDirection] = useState<'forward' | 'backward'>('forward');

  useEffect(() => {
    if (!open) {
      setState(mode ? (mode === 'events' ? 'event' : 'profile') : 'index');
    }
  }, [open, mode]);

  const shouldShowProperty = (property: string) => {
    return !exclude.find((ex) => {
      if (ex.endsWith('*')) {
        return property.startsWith(ex.slice(0, -1));
      }
      return property === ex;
    });
  };

  // Fixed group properties: name, type, plus dynamic property keys
  const groupActions = [
    { value: 'group.name', label: 'name', description: 'group' },
    { value: 'group.type', label: 'type', description: 'group' },
    ...(groupPropertiesQuery.data ?? []).map((key) => ({
      value: `group.properties.${key}`,
      label: key,
      description: 'group.properties',
    })),
  ].filter((a) => shouldShowProperty(a.value));

  const profileActions = properties
    .filter(
      (property) =>
        property.startsWith('profile') && shouldShowProperty(property)
    )
    .map((property) => ({
      value: property,
      label: property.split('.').pop() ?? property,
      description: property.split('.').slice(0, -1).join('.'),
    }));
  const eventActions = properties
    .filter(
      (property) =>
        !property.startsWith('profile') && shouldShowProperty(property)
    )
    .map((property) => ({
      value: property,
      label: property.split('.').pop() ?? property,
      description: property.split('.').slice(0, -1).join('.'),
    }));

  const handleStateChange = (
    newState: 'index' | 'event' | 'profile' | 'group'
  ) => {
    setDirection(newState === 'index' ? 'backward' : 'forward');
    setState(newState);
  };

  const handleSelect = (action: {
    value: string;
    label: string;
    description: string;
  }) => {
    setOpen(false);
    onSelect(action);
  };

  const renderIndex = () => {
    return (
      <DropdownMenuGroup>
        {/* <SearchHeader onSearch={() => {}} value={search} /> */}
        {/* <DropdownMenuSeparator /> */}
        <DropdownMenuItem
          className="group justify-between gap-2"
          onClick={(e) => {
            e.preventDefault();
            handleStateChange('event');
          }}
        >
          Event properties
          <DatabaseIcon className="size-4 transition-all group-hover:rotate-12 group-hover:scale-125 group-hover:text-blue-500" />
        </DropdownMenuItem>
        <DropdownMenuItem
          className="group justify-between gap-2"
          onClick={(e) => {
            e.preventDefault();
            handleStateChange('profile');
          }}
        >
          Profile properties
          <UserIcon className="size-4 transition-all group-hover:rotate-12 group-hover:scale-125 group-hover:text-blue-500" />
        </DropdownMenuItem>
        <DropdownMenuItem
          className="group justify-between gap-2"
          onClick={(e) => {
            e.preventDefault();
            handleStateChange('group');
          }}
        >
          Group properties
          <Building2Icon className="size-4 transition-all group-hover:rotate-12 group-hover:scale-125 group-hover:text-blue-500" />
        </DropdownMenuItem>
      </DropdownMenuGroup>
    );
  };

  const renderEvent = () => {
    const filteredActions = eventActions.filter(
      (action) =>
        action.label.toLowerCase().includes(search.toLowerCase()) ||
        action.description.toLowerCase().includes(search.toLowerCase())
    );

    return (
      <div className="col">
        <SearchHeader
          onBack={
            mode === undefined ? () => handleStateChange('index') : undefined
          }
          onSearch={setSearch}
          value={search}
        />
        <DropdownMenuSeparator />
        <VirtualList
          data={filteredActions}
          height={300}
          itemHeight={40}
          itemKey="id"
        >
          {(action) => (
            <motion.div
              animate={{ opacity: 1, y: 0 }}
              className="col cursor-pointer gap-px rounded-md p-2 hover:bg-accent"
              initial={{ opacity: 0, y: 10 }}
              onClick={() => handleSelect(action)}
            >
              <div className="font-medium">{action.label}</div>
              <div className="text-muted-foreground text-sm">
                {action.description}
              </div>
            </motion.div>
          )}
        </VirtualList>
      </div>
    );
  };

  const renderProfile = () => {
    const filteredActions = profileActions.filter(
      (action) =>
        action.label.toLowerCase().includes(search.toLowerCase()) ||
        action.description.toLowerCase().includes(search.toLowerCase())
    );

    return (
      <div className="flex flex-col">
        <SearchHeader
          onBack={() => handleStateChange('index')}
          onSearch={setSearch}
          value={search}
        />
        <DropdownMenuSeparator />
        <VirtualList
          data={filteredActions}
          height={300}
          itemHeight={40}
          itemKey="id"
        >
          {(action) => (
            <motion.div
              animate={{ opacity: 1, y: 0 }}
              className="col cursor-pointer gap-px rounded-md p-2 hover:bg-accent"
              initial={{ opacity: 0, y: 10 }}
              onClick={() => handleSelect(action)}
            >
              <div className="font-medium">{action.label}</div>
              <div className="text-muted-foreground text-sm">
                {action.description}
              </div>
            </motion.div>
          )}
        </VirtualList>
      </div>
    );
  };

  const renderGroup = () => {
    const filteredActions = groupActions.filter(
      (action) =>
        action.label.toLowerCase().includes(search.toLowerCase()) ||
        action.description.toLowerCase().includes(search.toLowerCase())
    );

    return (
      <div className="flex flex-col">
        <SearchHeader
          onBack={() => handleStateChange('index')}
          onSearch={setSearch}
          value={search}
        />
        <DropdownMenuSeparator />
        <VirtualList
          data={filteredActions}
          height={Math.min(300, filteredActions.length * 40 + 8)}
          itemHeight={40}
          itemKey="value"
        >
          {(action) => (
            <motion.div
              animate={{ opacity: 1, y: 0 }}
              className="col cursor-pointer gap-px rounded-md p-2 hover:bg-accent"
              initial={{ opacity: 0, y: 10 }}
              onClick={() => handleSelect(action)}
            >
              <div className="font-medium">{action.label}</div>
              <div className="text-muted-foreground text-sm">
                {action.description}
              </div>
            </motion.div>
          )}
        </VirtualList>
      </div>
    );
  };

  return (
    <DropdownMenu
      onOpenChange={(open) => {
        setOpen(open);
      }}
      open={open}
    >
      <DropdownMenuTrigger asChild>{children(setOpen)}</DropdownMenuTrigger>
      <DropdownMenuContent align="start" className="max-w-80">
        <AnimatePresence initial={false} mode="wait">
          {state === 'index' && (
            <motion.div
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              initial={{ opacity: 0 }}
              key="index"
              transition={{ duration: 0.05 }}
            >
              {renderIndex()}
            </motion.div>
          )}
          {state === 'event' && (
            <motion.div
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: direction === 'forward' ? -20 : 20 }}
              initial={{ opacity: 0, x: direction === 'forward' ? 20 : -20 }}
              key="event"
              transition={{ duration: 0.05 }}
            >
              {renderEvent()}
            </motion.div>
          )}
          {state === 'profile' && (
            <motion.div
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: direction === 'forward' ? -20 : 20 }}
              initial={{ opacity: 0, x: direction === 'forward' ? 20 : -20 }}
              key="profile"
              transition={{ duration: 0.05 }}
            >
              {renderProfile()}
            </motion.div>
          )}
          {state === 'group' && (
            <motion.div
              animate={{ opacity: 1, x: 0 }}
              exit={{ opacity: 0, x: direction === 'forward' ? -20 : 20 }}
              initial={{ opacity: 0, x: direction === 'forward' ? 20 : -20 }}
              key="group"
              transition={{ duration: 0.05 }}
            >
              {renderGroup()}
            </motion.div>
          )}
        </AnimatePresence>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
