import { useEffect, useState } from "react";
import { getMapObjectDisplayLabel, objectZoneId } from "../../lib/locationMapUtils";

export const MAP_DISPLAY_CONTROLS = [
  ["showZones", "Zones"],
  ["showLabels", "Labels"],
  ["showCounts", "Counts"],
  ["showPins", "Pins"],
  ["showMyItems", "Mine"],
  ["showOtherItems", "Others"],
  ["showCompleted", "Bought"],
  ["showUnmapped", "Unmapped"],
];

const MAP_ITEM_PREVIEW_LIMIT = 8;

function MapItemActionRow({ item, onSelectItem }) {
  const isBought = Boolean(item.bought);

  return (
    <li className={`location-map-item-row ${isBought ? "is-bought" : ""}`}>
      <button
        type="button"
        className="location-map-item-button"
        onClick={() => {
          if (!isBought) onSelectItem?.(item);
        }}
        disabled={isBought}
        aria-label={isBought ? `${item.item_name} bought` : `Mark ${item.item_name} bought`}
      >
        <span>{item.item_name}</span>
        <small>{isBought ? "Bought" : `x${item.quantity}`}</small>
      </button>
    </li>
  );
}

function MapItemActionList({ items, onSelectItem, itemGroupLabel }) {
  const [showAllItems, setShowAllItems] = useState(false);
  const itemListKey = items.map((item) => item.id).join(":");

  useEffect(() => {
    setShowAllItems(false);
  }, [itemListKey]);

  const visibleItems = showAllItems ? items : items.slice(0, MAP_ITEM_PREVIEW_LIMIT);
  const overflowItemCount = items.length - visibleItems.length;
  const hasOverflow = items.length > MAP_ITEM_PREVIEW_LIMIT;

  return (
    <ul>
      {visibleItems.map((item) => (
        <MapItemActionRow key={item.id} item={item} onSelectItem={onSelectItem} />
      ))}
      {hasOverflow ? (
        <li className="location-map-list-more">
          <button
            type="button"
            className="location-map-list-more-button"
            onClick={() => setShowAllItems((current) => !current)}
            aria-label={
              showAllItems
                ? `Show fewer ${itemGroupLabel}`
                : `Show ${overflowItemCount} more ${itemGroupLabel}`
            }
          >
            {showAllItems ? "Show fewer" : `+${overflowItemCount} more`}
          </button>
        </li>
      ) : null}
    </ul>
  );
}

export function LocationMapLayerPanel({ filters, setFilters }) {
  return (
    <div className="location-map-display-panel">
      <div className="location-map-display-controls">
        {MAP_DISPLAY_CONTROLS.map(([key, label]) => (
          <button
            key={key}
            type="button"
            className={filters[key] ? "active" : ""}
            aria-pressed={filters[key]}
            onClick={() =>
              setFilters((current) => ({ ...current, [key]: !current[key] }))
            }
          >
            <span
              className={`location-map-layer-state ${filters[key] ? "is-on" : ""}`}
              aria-hidden="true"
            />
            <span className="location-map-layer-label">{label}</span>
          </button>
        ))}
      </div>
    </div>
  );
}

export function LocationMapOverview({ ariaLabel, rows }) {
  return (
    <div className="location-map-overview" role="group" aria-label={ariaLabel}>
      {rows.map((row) => (
        <div className="location-map-overview-row" key={row.label}>
          <span>{row.label}</span>
          <strong>{row.value}</strong>
        </div>
      ))}
    </div>
  );
}

function InlineStateAction({ label, value, actionLabel, actionText = "Show", onAction }) {
  return (
    <div className="location-map-inline-state">
      <span>{label}</span>
      <strong>{value}</strong>
      {onAction ? (
        <button type="button" onClick={onAction} aria-label={actionLabel}>
          {actionText}
        </button>
      ) : null}
    </div>
  );
}

export function SelectedMapObjectForm({
  selectedObject,
  zones = [],
  saving,
  onObjectField,
  onZoneLinkChange,
  onDuplicateObject,
  onDeleteObject,
}) {
  const selectedObjectLabel = getMapObjectDisplayLabel(selectedObject);

  return (
    <div className="location-map-object-form">
      <label className="location-map-field-row">
        <span>Label</span>
        <input
          value={selectedObject.label || ""}
          disabled={saving}
          onChange={(event) => onObjectField("label", event.target.value)}
        />
      </label>
      <label className="location-map-field-row">
        <span>Zone</span>
        <select
          aria-label="Linked zone"
          value={objectZoneId(selectedObject)}
          disabled={saving}
          onChange={(event) => onZoneLinkChange(event.target.value)}
        >
          <option value="">No linked zone</option>
          {zones.map((zone) => (
            <option key={zone.id} value={zone.id}>{zone.name}</option>
          ))}
        </select>
      </label>
      <div className="location-map-object-flags">
        <button
          type="button"
          className={selectedObject.visible !== false ? "active" : ""}
          aria-pressed={selectedObject.visible !== false}
          disabled={saving}
          onClick={() => onObjectField("visible", selectedObject.visible === false)}
        >
          <span
            className={`location-map-object-flag-state ${selectedObject.visible !== false ? "is-on" : ""}`}
            aria-hidden="true"
          />
          <span className="location-map-object-flag-label">Visible</span>
        </button>
        <button
          type="button"
          className={selectedObject.locked ? "active" : ""}
          aria-pressed={Boolean(selectedObject.locked)}
          disabled={saving}
          onClick={() => onObjectField("locked", !selectedObject.locked)}
        >
          <span
            className={`location-map-object-flag-state ${selectedObject.locked ? "is-on" : ""}`}
            aria-hidden="true"
          />
          <span className="location-map-object-flag-label">Locked</span>
        </button>
      </div>
      <div className="location-map-editor-actions">
        <button
          type="button"
          onClick={onDuplicateObject}
          disabled={saving}
          aria-label={`Duplicate area ${selectedObjectLabel}`}
        >
          Duplicate
        </button>
        <button
          type="button"
          className="danger"
          onClick={onDeleteObject}
          disabled={saving}
          aria-label={`Delete area ${selectedObjectLabel}`}
        >
          Delete
        </button>
      </div>
    </div>
  );
}

export function SelectedZoneItemsPanel({
  selectedZoneItems,
  hasHiddenSelectedItems,
  hiddenSelectedItemCount,
  onShowSelectedZoneItems,
  onSelectZoneItem,
}) {
  if (selectedZoneItems.length === 0) {
    if (!hasHiddenSelectedItems) return null;

    return (
      <div className="location-map-zone-items">
        <div className="location-map-zone-empty">
          <InlineStateAction
            label="Hidden"
            value={hiddenSelectedItemCount}
            actionLabel="Show Zone Items"
            onAction={onShowSelectedZoneItems}
          />
        </div>
      </div>
    );
  }

  return (
    <div className="location-map-zone-items">
      <MapItemActionList
        items={selectedZoneItems}
        onSelectItem={onSelectZoneItem}
        itemGroupLabel="zone items"
      />
      {hasHiddenSelectedItems ? (
        <div className="location-map-zone-hidden-note">
          <InlineStateAction
            label="Hidden"
            value={hiddenSelectedItemCount}
            actionLabel="Show All Zone Items"
            actionText="Show All"
            onAction={onShowSelectedZoneItems}
          />
        </div>
      ) : null}
    </div>
  );
}

export function UnmappedItemsPanel({
  visibleUnmappedItems,
  hiddenUnmappedItemCount,
  hasHiddenUnmappedItems,
  onShowUnmappedItems,
  onSelectUnmappedItem,
}) {
  if (visibleUnmappedItems.length === 0 && hasHiddenUnmappedItems) {
    return (
      <div className="location-map-unmapped-list" aria-label="Unmapped items">
        <div className="location-map-zone-empty">
          <InlineStateAction
            label="Hidden"
            value={hiddenUnmappedItemCount}
            actionLabel="Show Unmapped Items"
            onAction={onShowUnmappedItems}
          />
        </div>
      </div>
    );
  }

  if (visibleUnmappedItems.length === 0) {
    return null;
  }

  return (
    <div className="location-map-unmapped-list" aria-label="Unmapped items">
      <MapItemActionList
        items={visibleUnmappedItems}
        onSelectItem={onSelectUnmappedItem}
        itemGroupLabel="unmapped items"
      />
      {hiddenUnmappedItemCount > 0 ? (
        <div className="location-map-zone-hidden-note">
          <InlineStateAction
            label="Hidden"
            value={hiddenUnmappedItemCount}
            actionLabel="Show All Unmapped Items"
            actionText="Show All"
            onAction={onShowUnmappedItems}
          />
        </div>
      ) : null}
    </div>
  );
}
