import { useMemo } from "react";
import {
  DEFAULT_MAP_FILTERS,
  getMapObjectDisplayLabel,
  objectZoneId,
} from "../../lib/locationMapUtils";
import {
  LocationMapLayerPanel,
  LocationMapOverview,
  MAP_DISPLAY_CONTROLS,
  SelectedMapObjectForm,
  SelectedZoneItemsPanel,
  UnmappedItemsPanel,
} from "./LocationMapBottomSheetSections";

const EMPTY_ITEMS = [];

export default function LocationMapBottomSheet({
  mode,
  editorTool,
  canManage,
  filters,
  setFilters,
  layersOpen,
  setLayersOpen,
  selectedObject,
  mapObjects = [],
  selectedZoneItems = EMPTY_ITEMS,
  visibleAssignedItemCount = 0,
  visibleUnmappedItems = EMPTY_ITEMS,
  unmappedItemCount,
  hiddenAreaCount,
  saving,
  savingAction,
  hasUnsavedChanges,
  mapState,
  onAddObject,
  onSaveDraft,
  onPublish,
  onPreviewDraft,
  onObjectField,
  onZoneLinkChange,
  onDuplicateObject,
  onDeleteObject,
  onShowHiddenAreas,
}) {
  const selectedTitle = getMapObjectDisplayLabel(selectedObject);
  const selectedZoneId = objectZoneId(selectedObject);
  const mapItems = mapState?.items || EMPTY_ITEMS;
  const { assignedItemCount, selectedAssignedItems } = useMemo(() => {
    const nextSelectedAssignedItems = [];
    let nextAssignedItemCount = 0;

    mapItems.forEach((item) => {
      if (!item.zone_id) return;
      nextAssignedItemCount += 1;
      if (selectedZoneId && String(item.zone_id) === selectedZoneId) {
        nextSelectedAssignedItems.push(item);
      }
    });

    return {
      assignedItemCount: nextAssignedItemCount,
      selectedAssignedItems: nextSelectedAssignedItems,
    };
  }, [mapItems, selectedZoneId]);
  const hiddenSelectedItemCount = Math.max(0, selectedAssignedItems.length - selectedZoneItems.length);
  const hasHiddenSelectedItems = hiddenSelectedItemCount > 0;
  const selectedItemCountLabel = hasHiddenSelectedItems
    ? `${selectedZoneItems.length} shown`
    : `${selectedZoneItems.length} item${selectedZoneItems.length === 1 ? "" : "s"}`;
  const sheetTitle = mode === "edit"
    ? selectedObject && editorTool === "edit"
      ? selectedTitle
      : editorTool === "edit"
        ? "Edit Areas"
        : "Move Map"
    : selectedObject
      ? selectedTitle
      : "Map Details";
  const showHeaderItemCount = mode !== "edit" && Boolean(selectedObject);
  const showEditorControls = mode === "edit" && canManage;
  const showSelectedObjectForm = Boolean(mode === "edit" && editorTool === "edit" && selectedObject);
  const changedLayerCount = useMemo(
    () => MAP_DISPLAY_CONTROLS.filter(([key]) => filters[key] !== DEFAULT_MAP_FILTERS[key]).length,
    [filters]
  );
  const totalAreaCount = mapObjects.length;
  const visibleAreaCount = filters.showZones
    ? Math.max(0, totalAreaCount - hiddenAreaCount)
    : 0;
  const hasNoVisibleAreas =
    filters.showZones && totalAreaCount > 0 && visibleAreaCount === 0 && hiddenAreaCount > 0;
  const showMapOverview = mode !== "edit" && !selectedObject;
  const unlinkedAreaCount = useMemo(
    () => mapObjects.filter((object) => !objectZoneId(object)).length,
    [mapObjects]
  );
  const showDraftOverview = mode === "edit" && editorTool === "edit" && !selectedObject;
  const hiddenUnmappedItemCount = Math.max(0, unmappedItemCount - visibleUnmappedItems.length);
  const hasHiddenUnmappedItems =
    filters.showUnmapped && unmappedItemCount > 0 && visibleUnmappedItems.length === 0;
  const hiddenAreaLabel = `Show Hidden Areas (${hiddenAreaCount})`;
  const showHiddenAreaAction =
    showEditorControls && hiddenAreaCount > 0 && filters.showZones && !hasNoVisibleAreas;
  const saveDraftLabel = savingAction === "save" ? "Saving..." : "Save Draft";
  const publishLabel = savingAction === "publish" ? "Publishing..." : "Publish";
  const mappedItemSummary = assignedItemCount === visibleAssignedItemCount
    ? String(assignedItemCount)
    : `${visibleAssignedItemCount} shown`;
  const unmappedItemSummary = !filters.showUnmapped && unmappedItemCount > 0
    ? `${unmappedItemCount} hidden`
    : visibleUnmappedItems.length === unmappedItemCount
      ? String(unmappedItemCount)
      : `${visibleUnmappedItems.length} shown`;
  const resetLayerFilters = () => setFilters({ ...DEFAULT_MAP_FILTERS });
  const showSelectedZoneItems = () => {
    setFilters((current) => ({
      ...current,
      showMyItems: true,
      showOtherItems: true,
      showCompleted: true,
    }));
  };
  const showUnmappedItems = () => {
    setFilters((current) => ({
      ...current,
      showUnmapped: true,
      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>
      {!showSelectedObjectForm ? (
        <button type="button" onClick={onPreviewDraft} aria-label="Preview Draft" disabled={saving}>
          Preview
        </button>
      ) : null}
    </div>
  ) : null;
  const editorActions = showEditorControls ? (
    <div className="location-map-editor-action-stack" role="group" aria-label="Map draft actions">
      {primaryDraftActions}
      {secondaryDraftActions}
    </div>
  ) : null;

  return (
    <aside className="location-map-bottom-sheet">
      <div className="location-map-bottom-sheet-handle" aria-hidden="true" />
      <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>
        </div>
        <div className="location-map-layer-actions">
          {changedLayerCount ? (
            <button
              type="button"
              className="location-map-layer-reset"
              onClick={resetLayerFilters}
              aria-label="Reset layer filters"
            >
              Reset
            </button>
          ) : null}
          <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>
      </div>

      {layersOpen ? (
        <LocationMapLayerPanel filters={filters} setFilters={setFilters} />
      ) : 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}

      {showHiddenAreaAction ? (
        <div className="location-map-hidden-areas">
          <button type="button" onClick={onShowHiddenAreas} disabled={saving}>
            {hiddenAreaLabel}
          </button>
        </div>
      ) : null}

      {showMapOverview ? (
        <LocationMapOverview
          ariaLabel="Map summary"
          rows={[
            { label: "Areas", value: filters.showZones ? `${visibleAreaCount} shown` : "Hidden" },
            { label: "Mapped items", value: mappedItemSummary },
            { label: "Unmapped", value: unmappedItemSummary },
          ]}
        />
      ) : null}

      {showDraftOverview ? (
        <LocationMapOverview
          ariaLabel="Draft map summary"
          rows={[
            { label: "Areas", value: totalAreaCount },
            { label: "Hidden", value: hiddenAreaCount },
            { label: "Unlinked", value: unlinkedAreaCount },
          ]}
        />
      ) : null}

      {mode === "edit" && editorTool === "edit" && selectedObject ? (
        <SelectedMapObjectForm
          selectedObject={selectedObject}
          zones={mapState?.zones || EMPTY_ITEMS}
          saving={saving}
          onObjectField={onObjectField}
          onZoneLinkChange={onZoneLinkChange}
          onDuplicateObject={onDuplicateObject}
          onDeleteObject={onDeleteObject}
        />
      ) : mode === "edit" ? (
        null
      ) : selectedObject ? (
        <SelectedZoneItemsPanel
          selectedZoneItems={selectedZoneItems}
          hasHiddenSelectedItems={hasHiddenSelectedItems}
          hiddenSelectedItemCount={hiddenSelectedItemCount}
          onShowSelectedZoneItems={showSelectedZoneItems}
        />
      ) : null}

      {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 ? (
        <UnmappedItemsPanel
          visibleUnmappedItems={visibleUnmappedItems}
          hiddenUnmappedItemCount={hiddenUnmappedItemCount}
          hasHiddenUnmappedItems={hasHiddenUnmappedItems}
          onShowUnmappedItems={showUnmappedItems}
        />
      ) : null}
    </aside>
  );
}
