import { Check, Eye, EyeOff, Lock, Map } from "lucide-react";
import { cn } from "@/lib/utils";
import type { BaseLayerOption } from "./base-layers-control";
import type { MapLayerControlItem } from "./layer-control";
import {
  MAP_COMPACT_RADIUS_CLASS_NAME,
  MAP_ICON_CELL_RADIUS_CLASS_NAME,
  MAP_READABLE_RADIUS_CLASS_NAME,
  MAP_READABLE_SURFACE_CLASS_NAME,
  MAP_READABLE_SURFACE_STRONG_CLASS_NAME
} from "./map-control-styles";

export type MapLayerPanelProps = {
  layerItems: MapLayerControlItem[];
  baseLayerOptions: BaseLayerOption[];
  activeBaseLayerId: string;
  onSelectBaseLayer: (id: string) => void;
  onToggleLayer: (id: string, visible: boolean) => void;
};

export function MapLayerPanel({
  layerItems,
  baseLayerOptions,
  activeBaseLayerId,
  onSelectBaseLayer,
  onToggleLayer
}: MapLayerPanelProps) {
  return (
    <>
      <LayerVisibilitySection items={layerItems} onToggleLayer={onToggleLayer} />
      <BaseLayerSection
        options={baseLayerOptions}
        activeLayerId={activeBaseLayerId}
        onSelectLayer={onSelectBaseLayer}
      />
    </>
  );
}

type LayerVisibilitySectionProps = {
  items: MapLayerControlItem[];
  onToggleLayer: (id: string, visible: boolean) => void;
};

function LayerVisibilitySection({ items, onToggleLayer }: LayerVisibilitySectionProps) {
  return (
    <div>
      <div className="mb-1.5 px-1 text-xs font-semibold text-slate-500">业务图层</div>
      <div className="grid grid-cols-3 gap-2">
        {items.map((item) => {
          const Icon = item.visible ? Eye : EyeOff;
          const disabled = item.disabled || item.locked;

          return (
            <button
              key={item.id}
              type="button"
              disabled={disabled}
              aria-pressed={item.visible}
              aria-label={`${item.label}${item.description ? `，${item.description}` : ""}`}
              title={item.description}
              onClick={() => onToggleLayer(item.id, !item.visible)}
              className={cn(
                "relative flex min-h-[76px] w-full flex-col items-center justify-center gap-1.5 border px-1.5 py-2 text-center transition duration-150 active:translate-y-px active:scale-[0.98]",
                MAP_COMPACT_RADIUS_CLASS_NAME,
                item.visible
                  ? "border-blue-200 bg-blue-50/90 text-blue-950 shadow-sm shadow-blue-950/5"
                  : "surface-well border-transparent text-slate-500 hover:border-slate-200 hover:bg-white",
                disabled && "cursor-not-allowed opacity-60 hover:bg-transparent"
              )}
            >
              <span
                className={cn(
                  "grid h-8 w-8 shrink-0 place-items-center transition-colors",
                  MAP_ICON_CELL_RADIUS_CLASS_NAME,
                  item.visible ? "bg-blue-600 text-white" : "bg-slate-100 text-slate-400"
                )}
              >
                {item.locked ? <Lock size={15} aria-hidden="true" /> : <Icon size={15} aria-hidden="true" />}
              </span>
              <span className="block w-full truncate text-xs font-semibold leading-tight">{item.label}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

type BaseLayerSectionProps = {
  options: BaseLayerOption[];
  activeLayerId: string;
  onSelectLayer: (id: string) => void;
};

function BaseLayerSection({ options, activeLayerId, onSelectLayer }: BaseLayerSectionProps) {
  return (
    <div>
      <div className="mb-1.5 flex items-center justify-between px-1">
        <span className="text-xs font-semibold text-slate-500">底图</span>
        <Map size={14} aria-hidden="true" className="text-slate-400" />
      </div>
      <div className="grid grid-cols-3 gap-2">
        {options.map((option) => {
          const active = option.id === activeLayerId;

          return (
            <button
              key={option.id}
              type="button"
              disabled={option.disabled}
              aria-pressed={active}
              onClick={() => onSelectLayer(option.id)}
              className={cn(
                "flex min-h-[76px] flex-col p-1 text-left transition duration-150",
                MAP_READABLE_RADIUS_CLASS_NAME,
                active ? MAP_READABLE_SURFACE_STRONG_CLASS_NAME : MAP_READABLE_SURFACE_CLASS_NAME,
                active
                  ? "border-blue-500 text-blue-700 ring-2 ring-blue-100"
                  : "text-slate-700 hover:border-blue-300 hover:bg-blue-50/40",
                option.disabled && "cursor-not-allowed opacity-50"
              )}
            >
              <BaseLayerSwatch option={option} active={active} />
              <span className="mt-1 block w-full truncate px-0.5 text-xs font-semibold leading-none">
                {option.label}
              </span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

type BaseLayerSwatchProps = {
  option: BaseLayerOption;
  active: boolean;
};

function BaseLayerSwatch({ option, active }: BaseLayerSwatchProps) {
  return (
    <span
      className={cn(
        "relative block min-h-0 flex-1 overflow-hidden border border-white shadow-inner",
        MAP_ICON_CELL_RADIUS_CLASS_NAME,
        option.swatchClassName ?? "bg-slate-100"
      )}
    >
      {active ? (
        <span className="absolute right-0.5 top-0.5 grid h-4 w-4 place-items-center rounded-full bg-blue-600 text-white">
          <Check size={10} aria-hidden="true" />
        </span>
      ) : null}
    </span>
  );
}
