import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { BASEMAPS, type BasemapId } from '../../lib/basemaps';
import { OVERLAYS, type OverlayDefinition, type OverlayId } from '../../lib/overlays';
import { CRIME_TYPES, CRIME_TYPE_VALUES } from '../../lib/crime-types';
import { PillToggle } from '../ui/PillToggle';
import { IconButton } from '../ui/IconButton';
import { Slider } from '../ui/Slider';
import InfoPopup from '../ui/InfoPopup';
import { CloseIcon, InfoIcon } from '../ui/icons';
import { colorOpacityToPercent, normalizeColorOpacity } from '../../lib/color-opacity';

const CRIME_OVERLAY_ID: OverlayId = 'crime-hotspots';

interface OverlayPaneProps {
  selectedOverlays: Set<OverlayId>;
  onOverlaysChange: (overlays: Set<OverlayId>) => void;
  selectedCrimeTypes: Set<string>;
  onCrimeTypesChange: (crimeTypes: Set<string>) => void;
  basemap: BasemapId;
  onBasemapChange: (basemap: BasemapId) => void;
  colorOpacity: number;
  onColorOpacityChange: (opacity: number) => void;
  zoomedIn: boolean;
  onClose?: () => void;
}

export default function OverlayPane({
  selectedOverlays,
  onOverlaysChange,
  selectedCrimeTypes,
  onCrimeTypesChange,
  basemap,
  onBasemapChange,
  colorOpacity,
  onColorOpacityChange,
  zoomedIn,
  onClose,
}: OverlayPaneProps) {
  const { t } = useTranslation();
  const [infoOverlay, setInfoOverlay] = useState<OverlayDefinition | null>(null);

  const toggleOverlay = (overlay: OverlayId) => {
    const next = new Set(selectedOverlays);
    if (next.has(overlay)) {
      next.delete(overlay);
    } else {
      next.add(overlay);
    }
    onOverlaysChange(next);
  };

  const crimeOverlayActive = selectedOverlays.has(CRIME_OVERLAY_ID);

  const toggleCrimeType = (value: string) => {
    const next = new Set(selectedCrimeTypes);
    if (next.has(value)) {
      next.delete(value);
    } else {
      next.add(value);
    }
    onCrimeTypesChange(next);
  };

  const selectAllCrimeTypes = () => onCrimeTypesChange(new Set(CRIME_TYPE_VALUES));
  const selectNoCrimeTypes = () => onCrimeTypesChange(new Set());

  const selectNone = () => onOverlaysChange(new Set());

  const showZoomWarning = !zoomedIn && selectedOverlays.size > 0;
  const colorOpacityPercent = colorOpacityToPercent(colorOpacity);
  const handleColorOpacityChange = ([value]: number[]) => {
    onColorOpacityChange(normalizeColorOpacity((value ?? colorOpacityPercent) / 100));
  };

  return (
    <div className="flex min-h-0 flex-col overflow-hidden bg-white shadow-lg dark:bg-warm-900">
      <div className="flex-shrink-0 px-3 pt-3 pb-2">
        <div className="flex items-center gap-2">
          <span className="text-xs font-semibold text-warm-500 dark:text-warm-400 uppercase tracking-wide">
            Overlays
          </span>
          <span className="text-xs text-warm-400 dark:text-warm-500">
            {selectedOverlays.size}/{OVERLAYS.length}
          </span>
          <div className="ml-auto flex items-center gap-1">
            <button
              onClick={selectNone}
              className="rounded border border-warm-300 px-2 py-0.5 text-xs text-warm-600 hover:bg-warm-50 dark:border-warm-700 dark:text-warm-400 dark:hover:bg-warm-700"
            >
              None
            </button>
            {onClose && (
              <button
                onClick={onClose}
                className="ml-1 p-0.5 text-warm-400 hover:text-warm-700 dark:hover:text-warm-300"
                title="Close"
              >
                <CloseIcon className="h-4 w-4" />
              </button>
            )}
          </div>
        </div>
        {showZoomWarning && (
          <div
            role="alert"
            className="mt-2 rounded border border-amber-300 bg-amber-50 px-2 py-1.5 text-xs text-amber-800 dark:border-amber-700/60 dark:bg-amber-900/30 dark:text-amber-200"
          >
            Zoom in further to see the selected{' '}
            {selectedOverlays.size === 1 ? 'overlay' : 'overlays'}.
          </div>
        )}
      </div>

      <div className="min-h-0 space-y-4 overflow-y-auto overscroll-contain border-t border-warm-200 px-3 py-3 dark:border-warm-700">
        <div>
          <div className="mb-2 text-[10px] font-semibold uppercase tracking-wide text-warm-400 dark:text-warm-500">
            Base map
          </div>
          <div className="flex flex-wrap gap-1.5">
            {BASEMAPS.map((option) => (
              <PillToggle
                key={option.id}
                label={option.label}
                active={basemap === option.id}
                onClick={() => onBasemapChange(option.id)}
                size="sm"
              />
            ))}
          </div>
        </div>

        <div>
          <div className="mb-2 flex items-center justify-between gap-2">
            <span className="text-[10px] font-semibold uppercase tracking-wide text-warm-400 dark:text-warm-500">
              Colour opacity
            </span>
            <span className="text-[10px] font-medium tabular-nums text-warm-500 dark:text-warm-400">
              {colorOpacityPercent}%
            </span>
          </div>
          <Slider
            min={10}
            max={100}
            step={5}
            value={[colorOpacityPercent]}
            onValueChange={handleColorOpacityChange}
            aria-label="Colour opacity"
          />
        </div>

        <div>
          <div className="mb-2 text-[10px] font-semibold uppercase tracking-wide text-warm-400 dark:text-warm-500">
            Data overlays
          </div>
          <div className="flex flex-wrap gap-1.5">
            {OVERLAYS.map((overlay) => (
              <div key={overlay.id} className="inline-flex items-center gap-0.5">
                <PillToggle
                  label={overlay.label}
                  active={selectedOverlays.has(overlay.id)}
                  onClick={() => toggleOverlay(overlay.id)}
                  size="sm"
                />
                <IconButton
                  onClick={() => setInfoOverlay(overlay)}
                  title={`About ${overlay.label}`}
                  ariaLabel={`About ${overlay.label}`}
                >
                  <InfoIcon className="h-3.5 w-3.5" />
                </IconButton>
              </div>
            ))}
          </div>
        </div>

        {crimeOverlayActive && (
          <div>
            <div className="mb-2 flex items-center gap-2">
              <span className="text-[10px] font-semibold uppercase tracking-wide text-warm-400 dark:text-warm-500">
                {t('filters.crimeType')}
              </span>
              <span className="text-[10px] text-warm-400 dark:text-warm-500">
                {selectedCrimeTypes.size}/{CRIME_TYPES.length}
              </span>
              <div className="ml-auto flex items-center gap-1">
                <button
                  onClick={selectAllCrimeTypes}
                  className="rounded border border-warm-300 px-1.5 py-0.5 text-[10px] text-warm-600 hover:bg-warm-50 dark:border-warm-700 dark:text-warm-400 dark:hover:bg-warm-700"
                >
                  All
                </button>
                <button
                  onClick={selectNoCrimeTypes}
                  className="rounded border border-warm-300 px-1.5 py-0.5 text-[10px] text-warm-600 hover:bg-warm-50 dark:border-warm-700 dark:text-warm-400 dark:hover:bg-warm-700"
                >
                  None
                </button>
              </div>
            </div>
            <div className="space-y-0.5">
              {CRIME_TYPES.map((crime) => (
                <label
                  key={crime.value}
                  className="flex cursor-pointer items-center gap-2 rounded px-1 py-0.5 text-xs text-warm-700 hover:bg-warm-50 dark:text-warm-300 dark:hover:bg-warm-800"
                >
                  <input
                    type="checkbox"
                    checked={selectedCrimeTypes.has(crime.value)}
                    onChange={() => toggleCrimeType(crime.value)}
                    className="h-3.5 w-3.5 shrink-0 rounded border-warm-300 text-amber-600 focus:ring-1 focus:ring-amber-500 dark:border-warm-600 dark:bg-warm-800"
                  />
                  <span>{crime.label}</span>
                </label>
              ))}
            </div>
          </div>
        )}
      </div>

      {infoOverlay && (
        <InfoPopup title={infoOverlay.label} onClose={() => setInfoOverlay(null)}>
          <p className="text-sm text-warm-700 dark:text-warm-300 leading-relaxed">
            {infoOverlay.detail}
          </p>
        </InfoPopup>
      )}
    </div>
  );
}
