import { useState, useRef, useCallback } from 'react';
import type { POICategoryGroup } from '../types';
import { useClickOutside } from '../hooks/useClickOutside';
import InfoPopup from './InfoPopup';

interface POIPaneProps {
  groups: POICategoryGroup[];
  selectedCategories: Set<string>;
  onCategoriesChange: (categories: Set<string>) => void;
  poiCount: number;
  onNavigateToSource?: (slug: string) => void;
}

export default function POIPane({
  groups,
  selectedCategories,
  onCategoriesChange,
  poiCount,
  onNavigateToSource,
}: POIPaneProps) {
  const [dropdownOpen, setDropdownOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(new Set());
  const [showInfo, setShowInfo] = useState(false);
  const dropdownRef = useRef<HTMLDivElement>(null);

  useClickOutside(dropdownRef, () => setDropdownOpen(false));

  const allCategories = groups.flatMap((g) => g.categories);

  const toggleCategory = (category: string) => {
    const newSet = new Set(selectedCategories);
    if (newSet.has(category)) {
      newSet.delete(category);
    } else {
      newSet.add(category);
    }
    onCategoriesChange(newSet);
  };

  const selectAll = () => {
    onCategoriesChange(new Set(allCategories));
  };

  const selectNone = () => {
    onCategoriesChange(new Set());
  };

  const toggleGroup = useCallback(
    (groupName: string) => {
      const group = groups.find((g) => g.name === groupName);
      if (!group) return;
      const allSelected = group.categories.every((c) => selectedCategories.has(c));
      const newSet = new Set(selectedCategories);
      if (allSelected) {
        group.categories.forEach((c) => newSet.delete(c));
      } else {
        group.categories.forEach((c) => newSet.add(c));
      }
      onCategoriesChange(newSet);
    },
    [groups, selectedCategories, onCategoriesChange]
  );

  const toggleCollapse = (groupName: string) => {
    setCollapsedGroups((prev) => {
      const next = new Set(prev);
      if (next.has(groupName)) {
        next.delete(groupName);
      } else {
        next.add(groupName);
      }
      return next;
    });
  };

  const lowerSearch = searchTerm.toLowerCase();

  const filteredGroups = groups
    .map((group) => {
      if (!searchTerm) return group;
      const matchingCats = group.categories.filter((c) => c.toLowerCase().includes(lowerSearch));
      const groupMatches = group.name.toLowerCase().includes(lowerSearch);
      if (groupMatches) return group;
      if (matchingCats.length === 0) return null;
      return { ...group, categories: matchingCats };
    })
    .filter(Boolean) as POICategoryGroup[];

  const selectedCount = selectedCategories.size;

  return (
    <div className="w-72 p-4 bg-white dark:bg-navy-950 shadow-lg space-y-4 overflow-y-auto max-h-screen">
      <div className="flex items-center gap-2">
        <h2 className="text-xl font-bold dark:text-warm-100">Points of Interest</h2>
        <button
          onClick={() => setShowInfo(true)}
          className="text-warm-400 hover:text-warm-700 dark:hover:text-warm-300 p-0.5 rounded"
          title="Data source info"
        >
          <svg
            className="w-3.5 h-3.5"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth={2}
          >
            <circle cx="12" cy="12" r="10" />
            <path strokeLinecap="round" d="M12 16v-4m0-4h.01" />
          </svg>
        </button>
      </div>

      {showInfo && (
        <InfoPopup
          title="Points of Interest"
          onClose={() => setShowInfo(false)}
          sourceLink={
            onNavigateToSource
              ? {
                  label: 'View data source',
                  onClick: () => {
                    onNavigateToSource('osm-pois');
                    setShowInfo(false);
                  },
                }
              : undefined
          }
        >
          <p className="text-sm text-warm-700 dark:text-warm-300 mb-4 leading-relaxed">
            Points of interest are sourced from OpenStreetMap via Geofabrik extracts. Categories
            include public transport stops, shops, restaurants, healthcare facilities, leisure
            venues, and more. Data is filtered and mapped to friendly names with exhaustive category
            coverage.
          </p>
        </InfoPopup>
      )}

      <div className="space-y-2" ref={dropdownRef}>
        <button
          onClick={() => setDropdownOpen(!dropdownOpen)}
          className="w-full flex items-center justify-between px-3 py-2 text-sm border border-warm-300 dark:border-navy-700 rounded hover:border-warm-400 bg-white dark:bg-navy-800 dark:text-warm-200"
        >
          <span className="truncate text-left">
            {selectedCount === 0
              ? 'Select categories...'
              : selectedCount === allCategories.length
                ? 'All categories'
                : `${selectedCount} selected`}
          </span>
          <svg
            className={`w-4 h-4 ml-2 flex-shrink-0 transition-transform ${dropdownOpen ? 'rotate-180' : ''}`}
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
          >
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
          </svg>
        </button>

        {dropdownOpen && (
          <div className="border border-warm-300 dark:border-navy-700 rounded shadow-lg bg-white dark:bg-navy-800">
            <div className="flex gap-2 px-3 py-2 border-b border-warm-200 dark:border-navy-700">
              <button
                onClick={selectAll}
                className="text-xs text-teal-600 dark:text-teal-400 hover:text-teal-800 dark:hover:text-teal-300"
              >
                All
              </button>
              <span className="text-xs text-warm-300 dark:text-warm-600">|</span>
              <button
                onClick={selectNone}
                className="text-xs text-teal-600 dark:text-teal-400 hover:text-teal-800 dark:hover:text-teal-300"
              >
                None
              </button>
            </div>
            <div className="px-3 py-2 border-b border-warm-200 dark:border-navy-700">
              <input
                type="text"
                placeholder="Search categories..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="w-full px-2 py-1 text-sm border border-warm-300 dark:border-navy-700 rounded bg-white dark:bg-navy-950 dark:text-warm-200 dark:placeholder-warm-500"
              />
            </div>
            <div className="max-h-96 overflow-y-auto py-1">
              {filteredGroups.map((group) => {
                const groupSelected = group.categories.filter((c) =>
                  selectedCategories.has(c)
                ).length;
                const allInGroupSelected = groupSelected === group.categories.length;
                const someInGroupSelected = groupSelected > 0 && !allInGroupSelected;
                const isCollapsed = collapsedGroups.has(group.name) && !searchTerm;

                return (
                  <div key={group.name}>
                    <div className="flex items-center gap-1 px-3 py-1.5 bg-warm-50 dark:bg-navy-950 border-y border-warm-100 dark:border-navy-700">
                      <button
                        onClick={() => toggleCollapse(group.name)}
                        className="p-0.5 text-warm-400 hover:text-warm-600"
                      >
                        <svg
                          className={`w-3 h-3 transition-transform ${isCollapsed ? '' : 'rotate-90'}`}
                          fill="none"
                          stroke="currentColor"
                          viewBox="0 0 24 24"
                        >
                          <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            strokeWidth={2}
                            d="M9 5l7 7-7 7"
                          />
                        </svg>
                      </button>
                      <label className="flex items-center gap-2 flex-1 cursor-pointer">
                        <input
                          type="checkbox"
                          checked={allInGroupSelected}
                          ref={(el) => {
                            if (el) el.indeterminate = someInGroupSelected;
                          }}
                          onChange={() => toggleGroup(group.name)}
                          className="rounded accent-teal-600"
                        />
                        <span className="text-xs font-semibold text-warm-700 dark:text-warm-300">
                          {group.name}
                        </span>
                      </label>
                      <span className="text-xs text-warm-400">
                        {groupSelected}/{group.categories.length}
                      </span>
                    </div>
                    {!isCollapsed &&
                      group.categories.map((category) => (
                        <label
                          key={category}
                          className="flex items-center gap-2 px-3 pl-8 py-1.5 hover:bg-warm-50 dark:hover:bg-navy-700 cursor-pointer dark:text-warm-300"
                        >
                          <input
                            type="checkbox"
                            checked={selectedCategories.has(category)}
                            onChange={() => toggleCategory(category)}
                            className="rounded accent-teal-600"
                          />
                          <span className="text-sm flex-1">{category}</span>
                        </label>
                      ))}
                  </div>
                );
              })}
            </div>
          </div>
        )}
      </div>

      {selectedCount > 0 && (
        <div className="p-3 bg-teal-50 dark:bg-teal-900/30 rounded text-sm">
          <div className="font-medium text-teal-900 dark:text-teal-300">
            {poiCount.toLocaleString()} POI{poiCount !== 1 ? 's' : ''} visible
          </div>
          <div className="text-xs text-teal-700 dark:text-teal-400 mt-1">
            {selectedCount} categor{selectedCount !== 1 ? 'ies' : 'y'} selected
          </div>
        </div>
      )}

      <div className="p-3 bg-warm-100 dark:bg-navy-800 rounded text-xs text-warm-600 dark:text-warm-400">
        <p>Select categories to display POIs on the map.</p>
        <p className="mt-2">Zoom in for better visibility of individual locations.</p>
      </div>
    </div>
  );
}
