import { DEFAULT_MAP_FILTERS, MAP_OBJECT_TYPES } from "../../lib/locationMapUtils";

function objectZoneId(object) {
  return object?.zone_id ? String(object.zone_id) : "";
}

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

export default function LocationMapBottomSheet({
  mode,
  editorTool,
  canManage,
  filters,
  setFilters,
  layersOpen,
  setLayersOpen,
  selectedObject,
  selectedZoneItems,
  visibleUnmappedItems,
  history,
  future,
  saving,
  savingAction,
  hasUnsavedChanges,
  mapState,
  mapSize,
  onAddObject,
  onUndo,
  onRedo,
  onSaveDraft,
  onPublish,
  onPreviewDraft,
  onPanMode,
  onEditObjects,
  onEditMode,
  onObjectField,
  onZoneLinkChange,
  onClearSelection,
  onDuplicateObject,
  onDeleteObject,
}) {
  const selectedTitle = selectedObject?.label || selectedObject?.zone_name || "Map Area";
  const selectedAssignedItems = selectedObject?.zone_id
    ? (mapState?.items || []).filter((item) => String(item.zone_id || "") === objectZoneId(selectedObject))
    : [];
  const hasHiddenSelectedItems = selectedAssignedItems.length > 0 && selectedZoneItems.length === 0;
  const selectedItemCountLabel = hasHiddenSelectedItems
    ? "0 shown"
    : `${selectedZoneItems.length} item${selectedZoneItems.length === 1 ? "" : "s"}`;
  const sheetTitle = mode === "edit"
    ? selectedObject && editorTool === "edit"
      ? selectedTitle
      : editorTool === "edit"
        ? "Edit Objects"
        : "Pan Mode"
    : selectedObject
      ? selectedTitle
      : "Map Details";
  const sheetDescription = selectedObject && editorTool === "edit"
    ? "Move, resize, link, rename, or nudge with arrow keys."
    : editorTool === "edit"
      ? "Tap an area to select it."
      : "Drag and zoom without changing objects.";
  const showHeaderItemCount = mode !== "edit" && Boolean(selectedObject);
  const showEditorControls = mode === "edit" && canManage;
  const showSelectedObjectForm = Boolean(mode === "edit" && editorTool === "edit" && selectedObject);
  const changedLayerCount = DISPLAY_CONTROLS.filter(([key]) => filters[key] !== DEFAULT_MAP_FILTERS[key]).length;
  const unmappedItemPreview = visibleUnmappedItems.slice(0, 8);
  const hiddenUnmappedItemCount = visibleUnmappedItems.length - unmappedItemPreview.length;
  const selectedWidth = Number(selectedObject?.width) || 40;
  const selectedHeight = Number(selectedObject?.height) || 40;
  const maxX = Math.max(0, Math.round((mapSize?.width || selectedWidth) - selectedWidth));
  const maxY = Math.max(0, Math.round((mapSize?.height || selectedHeight) - selectedHeight));
  const maxWidth = Math.max(40, Math.round(mapSize?.width || selectedWidth));
  const maxHeight = Math.max(40, Math.round(mapSize?.height || selectedHeight));
  const saveDraftLabel = savingAction === "save" ? "Saving..." : "Save Draft";
  const publishLabel = savingAction === "publish" ? "Publishing..." : "Publish";
  const showSelectedZoneItems = () => {
    setFilters((current) => ({
      ...current,
      showMyItems: true,
      showOtherItems: true,
      showCompleted: true,
    }));
  };
  const primaryDraftActions = showEditorControls ? (
    <div className="location-map-editor-actions location-map-primary-actions">
      <button type="button" className="primary" onClick={onSaveDraft} disabled={saving || !hasUnsavedChanges}>
        {saveDraftLabel}
      </button>
      <button
        type="button"
        className="primary"
        onClick={onPublish}
        disabled={saving || (!mapState?.draft_map && !hasUnsavedChanges)}
      >
        {publishLabel}
      </button>
    </div>
  ) : null;
  const secondaryDraftActions = showEditorControls ? (
    <div className="location-map-editor-actions location-map-secondary-actions">
      <button type="button" onClick={onAddObject} disabled={saving}>Add Area</button>
      <button type="button" onClick={onPreviewDraft} aria-label="Preview Draft" disabled={saving}>Preview</button>
      <button type="button" onClick={onUndo} disabled={saving || history.length === 0}>Undo</button>
      <button type="button" onClick={onRedo} disabled={saving || future.length === 0}>Redo</button>
    </div>
  ) : null;
  const editorActions = showEditorControls ? (
    <div className="location-map-editor-action-stack" role="group" aria-label="Map draft actions">
      {primaryDraftActions}
      {secondaryDraftActions}
    </div>
  ) : canManage && mapState?.published_map ? (
    <div className="location-map-editor-actions">
      <button type="button" onClick={onEditMode}>Edit Map</button>
    </div>
  ) : null;

  return (
    <aside className="location-map-bottom-sheet">
      <div className="location-map-sheet-header">
        <div>
          <div className="location-map-sheet-heading">
            <strong>{sheetTitle}</strong>
            {showHeaderItemCount ? (
              <span className="location-map-sheet-count">{selectedItemCountLabel}</span>
            ) : null}
          </div>
          {mode === "edit" && canManage ? (
            <span>{sheetDescription}</span>
          ) : null}
        </div>
        <button
          type="button"
          className={`location-map-layer-toggle ${layersOpen ? "active" : ""}`}
          onClick={() => setLayersOpen((current) => !current)}
          aria-expanded={layersOpen}
          aria-label={changedLayerCount ? `Layers, ${changedLayerCount} changed` : "Layers"}
        >
          Layers
          {changedLayerCount ? (
            <span className="location-map-layer-count" aria-hidden="true">{changedLayerCount}</span>
          ) : null}
        </button>
      </div>

      {layersOpen ? (
        <div className="location-map-display-panel">
          {changedLayerCount ? (
            <button
              type="button"
              className="location-map-layer-reset"
              onClick={() => setFilters({ ...DEFAULT_MAP_FILTERS })}
            >
              Reset
            </button>
          ) : null}
          <div className="location-map-display-controls">
            {DISPLAY_CONTROLS.map(([key, label]) => (
              <label key={key}>
                <input
                  type="checkbox"
                  checked={filters[key]}
                  onChange={(event) =>
                    setFilters((current) => ({ ...current, [key]: event.target.checked }))
                  }
                />
                {label}
              </label>
            ))}
          </div>
        </div>
      ) : null}

      {showSelectedObjectForm && primaryDraftActions ? (
        <div
          className="location-map-editor-action-stack location-map-selected-primary-actions"
          role="group"
          aria-label="Map draft actions"
        >
          {primaryDraftActions}
        </div>
      ) : editorActions}

      {showEditorControls ? (
        <div className="location-map-mobile-tool-switch" aria-label="Edit tool">
          <button
            type="button"
            className={[editorTool === "pan" ? "active" : "", "is-pan"].filter(Boolean).join(" ")}
            onClick={onPanMode}
            disabled={saving}
          >
            Pan
          </button>
          <button
            type="button"
            className={[editorTool === "edit" ? "active" : "", "is-edit"].filter(Boolean).join(" ")}
            onClick={onEditObjects}
            disabled={saving}
          >
            Objects
          </button>
        </div>
      ) : null}

      {mode === "edit" && editorTool === "edit" && selectedObject ? (
        <div className="location-map-object-form">
          <label>
            Label
            <input
              value={selectedObject.label || ""}
              disabled={saving}
              onChange={(event) => onObjectField("label", event.target.value)}
            />
          </label>
          <label>
            Type
            <select
              aria-label="Object type"
              value={selectedObject.type}
              disabled={saving}
              onChange={(event) => onObjectField("type", event.target.value)}
            >
              {MAP_OBJECT_TYPES.map((type) => (
                <option key={type} value={type}>{type}</option>
              ))}
            </select>
          </label>
          <label>
            Zone
            <select
              aria-label="Linked zone"
              value={objectZoneId(selectedObject)}
              disabled={saving}
              onChange={(event) => onZoneLinkChange(event.target.value)}
            >
              <option value="">No linked zone</option>
              {(mapState?.zones || []).map((zone) => (
                <option key={zone.id} value={zone.id}>{zone.name}</option>
              ))}
            </select>
          </label>
          <div className="location-map-object-grid">
            <label>
              X
              <input
                type="number"
                min="0"
                max={maxX}
                step="1"
                value={Math.round(selectedObject.x)}
                disabled={saving}
                onChange={(event) => onObjectField("x", Number(event.target.value))}
              />
            </label>
            <label>
              Y
              <input
                type="number"
                min="0"
                max={maxY}
                step="1"
                value={Math.round(selectedObject.y)}
                disabled={saving}
                onChange={(event) => onObjectField("y", Number(event.target.value))}
              />
            </label>
            <label>
              W
              <input
                type="number"
                min="40"
                max={maxWidth}
                step="1"
                value={Math.round(selectedObject.width)}
                disabled={saving}
                onChange={(event) => onObjectField("width", Number(event.target.value))}
              />
            </label>
            <label>
              H
              <input
                type="number"
                min="40"
                max={maxHeight}
                step="1"
                value={Math.round(selectedObject.height)}
                disabled={saving}
                onChange={(event) => onObjectField("height", Number(event.target.value))}
              />
            </label>
          </div>
          <div className="location-map-editor-actions">
            <button type="button" onClick={onClearSelection}>Done</button>
            <button type="button" onClick={onDuplicateObject} disabled={saving}>Duplicate</button>
            <button type="button" className="danger" onClick={onDeleteObject} disabled={saving}>Delete</button>
          </div>
        </div>
      ) : mode === "edit" && editorTool === "edit" ? (
        <p className="location-map-muted">
          Tap an area to edit its name, linked zone, size, and position.
        </p>
      ) : mode === "edit" ? (
        <p className="location-map-muted">
          Use Pan Mode to move around the map. Switch to Objects when you want to edit areas.
        </p>
      ) : selectedObject ? (
        <div className="location-map-zone-items">
          {selectedZoneItems.length === 0 ? (
            <div className="location-map-zone-empty">
              <p className="location-map-muted">
                {hasHiddenSelectedItems
                  ? "Items are assigned here, but hidden by layer filters."
                  : "No items assigned to this zone yet."}
              </p>
              {hasHiddenSelectedItems ? (
                <button type="button" onClick={showSelectedZoneItems}>
                  Show Zone Items
                </button>
              ) : null}
            </div>
          ) : (
            <ul>
              {selectedZoneItems.map((item) => (
                <li key={item.id}>
                  <span>{item.item_name}</span>
                  <small>x{item.quantity}</small>
                </li>
              ))}
            </ul>
          )}
        </div>
      ) : (
        <p className="location-map-muted">
          Tap a zone to view assigned items. Item pins stay hidden unless you turn them on in Layers.
        </p>
      )}

      {showSelectedObjectForm && secondaryDraftActions ? (
        <div
          className="location-map-editor-action-stack location-map-selected-secondary-actions"
          role="group"
          aria-label="More map draft actions"
        >
          {secondaryDraftActions}
        </div>
      ) : null}

      {filters.showUnmapped && visibleUnmappedItems.length > 0 ? (
        <div className="location-map-unmapped-list">
          <strong>Unmapped Items</strong>
          <ul>
            {unmappedItemPreview.map((item) => (
              <li key={item.id}>{item.item_name}</li>
            ))}
            {hiddenUnmappedItemCount > 0 ? (
              <li
                className="location-map-unmapped-more"
                aria-label={`${hiddenUnmappedItemCount} more unmapped items`}
              >
                +{hiddenUnmappedItemCount} more
              </li>
            ) : null}
          </ul>
        </div>
      ) : null}
    </aside>
  );
}
