import { useState, useCallback, useMemo } from 'react';
import {
  Text,
  Loader,
  Group,
  Badge,
  TextInput,
  UnstyledButton,
  Collapse,
  Stack,
  Box,
  rem,
  Center,
  useComputedColorScheme,
} from '@mantine/core';
import {
  IconChevronRight,
  IconChevronDown,
  IconSearch,
  IconMapPin,
} from '@tabler/icons-react';
import { useGetLocationsQuery } from '../api/location-api';
import type { Location } from '../types/location';
import { useTranslation } from 'react-i18next';
import { useLocalized } from '@ema-platform/api';
import { PageLoader } from '@ema-platform/ui';

interface LocationTreeProps {
  selectedId: string | null;
  onSelect: (location: Location) => void;
}

function flatListToTree(
  items: Location[],
  parentId: string | null,
): Location[] {
  return items
    .filter((item) => item.parentId === parentId)
    .map((item) => ({
      ...item,
      children: flatListToTree(items, item.id),
    }));
}

function TreeNode({
  location,
  selectedId,
  onSelect,
  depth,
}: {
  location: Location;
  selectedId: string | null;
  onSelect: (location: Location) => void;
  depth: number;
}) {
  const localized = useLocalized();
  const [opened, setOpened] = useState(depth < 1);
  const isSelected = selectedId === location.id;
  const hasChildren =
    Array.isArray(location.children) && location.children.length > 0;
  const colorScheme = useComputedColorScheme('light', { getInitialValueInEffect: true });
  const hoverBg = colorScheme === 'dark'
    ? 'var(--mantine-color-dark-6)'
    : 'var(--mantine-color-gray-0)';

  const toggle = useCallback(() => {
    setOpened((prev) => !prev);
  }, []);

  const select = useCallback(() => {
    onSelect(location);
  }, [onSelect, location]);

  return (
    <Box>
      <UnstyledButton
        onClick={select}
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: rem(6),
          width: '100%',
          padding: `${rem(6)} ${rem(8)}`,
          paddingLeft: rem(12 + depth * 20),
          borderRadius: rem(8),
          backgroundColor: isSelected
            ? 'var(--mantine-color-blue-light)'
            : 'transparent',
          color: isSelected
            ? 'var(--mantine-color-blue-filled)'
            : 'var(--mantine-color-text)',
          cursor: 'pointer',
          border: 'none',
          fontSize: rem(14),
          transition: 'background-color 100ms ease',
        }}
        onMouseEnter={(e) => {
          if (!isSelected)
            e.currentTarget.style.backgroundColor = hoverBg;
        }}
        onMouseLeave={(e) => {
          if (!isSelected)
            e.currentTarget.style.backgroundColor = 'transparent';
        }}
      >
        {hasChildren && (
          <Box
            component="button"
            onClick={(e: React.MouseEvent) => {
              e.stopPropagation();
              toggle();
            }}
            style={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              width: rem(18),
              height: rem(18),
              border: 'none',
              background: 'none',
              cursor: 'pointer',
              padding: 0,
              flexShrink: 0,
            }}
          >
            {opened ? (
              <IconChevronDown size={14} stroke={1.5} />
            ) : (
              <IconChevronRight size={14} stroke={1.5} />
            )}
          </Box>
        )}
        {!hasChildren && <Box w={rem(18)} style={{ flexShrink: 0 }} />}
        <IconMapPin
          size={14}
          stroke={1.5}
          style={{ flexShrink: 0, opacity: 0.6 }}
        />
        <Text size="sm" truncate style={{ flex: 1 }}>
          {localized(location.names)}
        </Text>
      </UnstyledButton>
      {hasChildren && (
        <Collapse in={opened}>
          <Stack gap={2} mt={2}>
            {location.children!.map((child) => (
              <TreeNode
                key={child.id}
                location={child}
                selectedId={selectedId}
                onSelect={onSelect}
                depth={depth + 1}
              />
            ))}
          </Stack>
        </Collapse>
      )}
    </Box>
  );
}

export function LocationTree({
  selectedId,
  onSelect,
}: LocationTreeProps) {
  const { t } = useTranslation();
  const [search, setSearch] = useState('');

  const { data: allLocationsRes, isLoading } = useGetLocationsQuery({ take: 10000 });

  const tree = useMemo(() => {
    if (!allLocationsRes?.items) return [];
    const roots = flatListToTree(allLocationsRes.items, null);
    return roots;
  }, [allLocationsRes]);

  const filteredTree = useMemo(() => {
    if (!search) return tree;

    const matches = (loc: Location): boolean => {
      const nameMatch = (loc.names.en ?? '')
        .toLowerCase()
        .includes(search.toLowerCase());
      const childMatch =
        Array.isArray(loc.children) &&
        loc.children.some(matches);
      return nameMatch || childMatch;
    };

    const filterNodes = (nodes: Location[]): Location[] =>
      nodes
        .filter(matches)
        .map((node) => ({
          ...node,
          children: Array.isArray(node.children)
            ? filterNodes(node.children)
            : [],
        }));

    return filterNodes(tree);
  }, [tree, search]);

  const handleSelect = useCallback(
    (loc: Location) => {
      onSelect(loc);
    },
    [onSelect],
  );

  if (isLoading) {
    return <PageLoader label="Loading Locations…" height={300} />;
  }

  return (
    <>
      <TextInput
        placeholder={t('location.search')}
        leftSection={<IconSearch size={16} />}
        value={search}
        onChange={(e) => setSearch(e.currentTarget.value)}
        mb="sm"
        size="sm"
      />
      {tree.length === 0 && (
        <Text c="dimmed" size="sm" ta="center" py="xl">
          {t('location.noLocations')}
        </Text>
      )}
      <Stack gap={2}>
        {filteredTree.map((root) => (
          <TreeNode
            key={root.id}
            location={root}
            selectedId={selectedId}
            onSelect={handleSelect}
            depth={0}
          />
        ))}
      </Stack>
    </>
  );
}
