import { useState, useMemo, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useCollapsibleGroups } from '../../hooks/useCollapsibleGroups';
import { useTravelModes } from '../../hooks/useTravelModes';
import { SearchInput } from '../ui/SearchInput';
import { FilterIcon } from '../ui/icons';
import { CollapsibleGroupHeader } from '../ui/CollapsibleGroupHeader';
import { EmptyState } from '../ui/EmptyState';
import type { FeatureMeta } from '../../types';
import { groupFeaturesByCategory } from '../../lib/features';
import { FeatureInfoPopup } from '../ui/FeatureInfoPopup';
import { FeatureActions } from '../ui/FeatureIcons';
import { FeatureLabel } from '../ui/FeatureLabel';
import { PlusIcon, InfoIcon } from '../ui/icons';
import { IconButton } from '../ui/IconButton';
import { TravelTimeInfoPopup } from '../ui/TravelTimeInfoPopup';
import {
  TRANSPORT_MODES,
  MODE_ICONS,
  useTranslatedModes,
  type TransportMode,
  type TravelTimeEntry,
} from '../../hooks/useTravelTime';

interface FeatureBrowserProps {
  availableFeatures: FeatureMeta[];
  allFeatures: FeatureMeta[];
  pinnedFeature: string | null;
  onAddFilter: (name: string) => void;
  onTogglePin: (name: string) => void;
  onNavigateToSource?: (slug: string, featureName: string) => void;
  openInfoFeature?: string | null;
  onClearOpenInfoFeature?: () => void;
  travelTimeEntries: TravelTimeEntry[];
  onAddTravelTimeEntry: (mode: TransportMode) => void;
}

export default function FeatureBrowser({
  availableFeatures,
  allFeatures,
  pinnedFeature,
  onAddFilter,
  onTogglePin,
  onNavigateToSource,
  openInfoFeature,
  onClearOpenInfoFeature,
  travelTimeEntries: _travelTimeEntries,
  onAddTravelTimeEntry,
}: FeatureBrowserProps) {
  const { t } = useTranslation();
  const modes = useTranslatedModes();
  const [search, setSearch] = useState('');
  const [infoFeature, setInfoFeature] = useState<FeatureMeta | null>(null);
  const [travelInfoMode, setTravelInfoMode] = useState<TransportMode | null>(null);
  const [isGroupExpanded, toggleGroup] = useCollapsibleGroups(true);
  const availableTravelModes = useTravelModes();

  useEffect(() => {
    if (openInfoFeature) {
      const feat = allFeatures.find((f) => f.name === openInfoFeature);
      if (feat) setInfoFeature(feat);
      onClearOpenInfoFeature?.();
    }
  }, [openInfoFeature, allFeatures, onClearOpenInfoFeature]);

  const filtered = useMemo(() => {
    if (!search) return availableFeatures;
    const lower = search.toLowerCase();
    return availableFeatures.filter((f) =>
      [f.name, f.description, f.detail, f.group]
        .filter((value): value is string => Boolean(value))
        .some((value) => value.toLowerCase().includes(lower))
    );
  }, [availableFeatures, search]);

  const grouped = useMemo(() => groupFeaturesByCategory(filtered), [filtered]);

  // When searching, expand all groups so results are visible
  const isSearching = search.length > 0;

  // Only show modes that have precomputed travel time data
  const visibleModes = useMemo(
    () => (availableTravelModes ? TRANSPORT_MODES.filter((m) => availableTravelModes.has(m)) : []),
    [availableTravelModes]
  );

  const showTravelModes =
    visibleModes.length > 0 &&
    (!search || t('filters.travelTimeKeywords').toLowerCase().includes(search.toLowerCase()));

  // Keep "Transport" first because journey and transport proximity controls belong together.
  const mergedGrouped = useMemo(() => {
    const transportGroup = grouped.find((g) => g.name === 'Transport');
    const otherGroups = grouped.filter((g) => g.name !== 'Transport');
    if (transportGroup) return [transportGroup, ...otherGroups];
    if (showTravelModes) return [{ name: 'Transport', features: [] }, ...otherGroups];
    return otherGroups;
  }, [grouped, showTravelModes]);

  return (
    <>
      <div className="shrink-0 p-2 border-b border-warm-200 dark:border-navy-700">
        <SearchInput
          value={search}
          onChange={setSearch}
          placeholder={t('filters.searchFeatures')}
        />
        {!search && (
          <p className="mt-2 px-1 text-xs leading-relaxed text-warm-500 dark:text-warm-400">
            {t('filters.chooseFilters')}
          </p>
        )}
      </div>
      <div>
        {mergedGrouped.map((group) => {
          const isExpanded = isSearching || isGroupExpanded(group.name);
          return (
            <div key={group.name} className="shrink-0">
              <CollapsibleGroupHeader
                name={group.name}
                expanded={isExpanded}
                onToggle={() => toggleGroup(group.name)}
                className="px-3 py-2.5 text-sm font-bold text-navy-950 bg-warm-200 dark:bg-navy-900 dark:text-warm-100 sticky top-0 z-30 hover:bg-warm-200 dark:hover:bg-warm-800"
              >
                <span className="text-xs font-medium text-warm-400 dark:text-warm-500">
                  {group.features.length +
                    (group.name === 'Transport' && showTravelModes ? visibleModes.length : 0)}
                </span>
              </CollapsibleGroupHeader>
              {isExpanded && (
                <>
                  {group.name === 'Transport' &&
                    showTravelModes &&
                    visibleModes.map((mode) => {
                      const ModeIcon = MODE_ICONS[mode];
                      return (
                        <div
                          key={mode}
                          className="flex items-center justify-between px-3 py-1.5 hover:bg-teal-50 dark:hover:bg-teal-900/30 cursor-pointer"
                        >
                          <div
                            className="flex items-center gap-2 min-w-0"
                            onClick={() => onAddTravelTimeEntry(mode)}
                          >
                            <ModeIcon className="w-4 h-4 text-teal-600 dark:text-teal-400 shrink-0" />
                            <div className="min-w-0">
                              <span className="text-sm font-medium text-navy-950 dark:text-warm-100">
                                {modes.label(mode)}
                              </span>
                              <span className="text-xs text-warm-400 dark:text-warm-500 block">
                                {modes.desc(mode)}
                              </span>
                            </div>
                          </div>
                          <div className="flex items-center gap-0.5 shrink-0">
                            <IconButton
                              onClick={() => setTravelInfoMode(mode)}
                              title={t('filters.aboutData')}
                              size="md"
                            >
                              <InfoIcon className="w-4 h-4" />
                            </IconButton>
                            <button
                              type="button"
                              onClick={() => onAddTravelTimeEntry(mode)}
                              title={t('travel.addTravelTime', { mode: modes.label(mode) })}
                              aria-label={t('travel.addTravelTime', { mode: modes.label(mode) })}
                              className="inline-flex items-center gap-1 rounded-md bg-teal-50 px-2 py-1 text-xs font-semibold text-teal-700 hover:bg-teal-100 dark:bg-teal-900/30 dark:text-teal-300 dark:hover:bg-teal-800/40"
                            >
                              <PlusIcon className="w-4 h-4" strokeWidth={2.5} />
                              <span>{t('filters.addFilterAction')}</span>
                            </button>
                          </div>
                        </div>
                      );
                    })}
                  {group.features.map((f) => {
                    const isPinned = pinnedFeature === f.name;
                    return (
                      <div
                        key={f.name}
                        className="flex items-center justify-between px-3 py-1.5 hover:bg-teal-50 dark:hover:bg-teal-900/30 dark:text-warm-300"
                      >
                        <div className="min-w-0 mr-2">
                          <FeatureLabel feature={f} size="sm" description={f.description} />
                        </div>
                        <FeatureActions
                          feature={f}
                          isPinned={isPinned}
                          onTogglePin={onTogglePin}
                          onShowInfo={setInfoFeature}
                          onAdd={onAddFilter}
                          showText
                        />
                      </div>
                    );
                  })}
                </>
              )}
            </div>
          );
        })}
        {mergedGrouped.length === 0 ? (
          <EmptyState
            icon={<FilterIcon className="w-8 h-8 text-warm-300 dark:text-warm-600" />}
            title={search ? t('filters.noMatchingFeatures') : t('filters.allFeaturesActive')}
            description={search ? t('filters.tryDifferentSearch') : t('filters.removeFilterHint')}
            className="px-3 py-4"
          />
        ) : null}
      </div>
      {infoFeature && (
        <FeatureInfoPopup
          feature={infoFeature}
          onClose={() => setInfoFeature(null)}
          onNavigateToSource={onNavigateToSource}
        />
      )}
      {travelInfoMode && (
        <TravelTimeInfoPopup mode={travelInfoMode} onClose={() => setTravelInfoMode(null)} />
      )}
    </>
  );
}
