'use client';

import { useState } from 'react';

import { GRID_ZOOM_STEPS } from '../constants';
import { useGallery, useGalleryStoreApi } from '../store/context';
import { mediaForView } from '../store/selectors';
import type { GridFilter } from '../store/store';
import type { AlbumId, LibraryScale, MapMode, ViewId } from '../types';
import { confirmAction, openSecuritySettings, openShareModal } from './modals';
import { openUploadModal } from './UploadModal';
import { openContextMenu } from './ContextMenu';
import { Icon } from '../icons';

function Segmented<T extends string>({
  options,
  value,
  onChange,
}: {
  options: Array<{ value: T; label: string }>;
  value: T;
  onChange: (v: T) => void;
}) {
  return (
    <div className="apg-segmented" role="tablist">
      {options.map((o) => (
        <button
          key={o.value}
          type="button"
          role="tab"
          aria-selected={value === o.value}
          className={['apg-segmented__item', value === o.value ? 'apg-segmented__item--active' : '']
            .filter(Boolean)
            .join(' ')}
          onClick={() => onChange(o.value)}
        >
          {o.label}
        </button>
      ))}
    </div>
  );
}

const GRID_VIEWS = new Set<string>([
  'library',
  'favourites',
  'recently-saved',
  'videos',
  'screenshots',
  'recently-deleted',
  'duplicates',
  'search',
]);

const SCALE_OPTIONS: Array<{ value: LibraryScale; label: string }> = [
  { value: 'years', label: 'Years' },
  { value: 'months', label: 'Months' },
  { value: 'all', label: 'All Photos' },
];

const FILTER_OPTIONS: Array<{ value: GridFilter; label: string }> = [
  { value: 'all', label: 'All Items' },
  { value: 'favourites', label: 'Favourites' },
  { value: 'edited', label: 'Edited' },
  { value: 'photos', label: 'Photos' },
  { value: 'videos', label: 'Videos' },
  { value: 'screenshots', label: 'Screenshots' },
  { value: 'not-in-album', label: 'Not in an Album' },
];

export function TopToolbar() {
  const api = useGalleryStoreApi();
  const view = useGallery((s) => s.view);
  const libraryScale = useGallery((s) => s.libraryScale);
  const mapMode = useGallery((s) => s.mapMode);
  const gridFilter = useGallery((s) => s.gridFilter);
  const searchQuery = useGallery((s) => s.searchQuery);
  const zoomIndex = useGallery((s) => s.zoomIndex);
  const features = useGallery((s) => s.config.features);
  const theme = useGallery((s) => s.theme);
  // A host that owns light/dark must not be overridden from inside the gallery.
  const showThemeSwitcher = useGallery((s) => s.config.chrome.themeSwitcher);
  const aiStatus = useGallery((s) => s.aiStatus);
  const infoOpen = useGallery((s) => s.infoOpen);
  const fullscreen = useGallery((s) => s.fullscreen);
  const selectionCount = useGallery((s) => s.selection.size);

  const [searchExpanded, setSearchExpanded] = useState(false);

  const isGrid = GRID_VIEWS.has(view) || view.startsWith('album:');
  const isAlbumish = view !== 'library' && view !== 'collections';
  // Uploads default into the album you're viewing (else Library).
  const currentAlbumId = view.startsWith('album:') ? (view as unknown as AlbumId) : undefined;

  const openFilterMenu = (e: React.MouseEvent) => {
    const r = (e.currentTarget as HTMLElement).getBoundingClientRect();
    openContextMenu(
      r.left,
      r.bottom + 4,
      FILTER_OPTIONS.map((o) => ({
        label: o.label,
        checked: gridFilter === o.value,
        onClick: () => api.getState().setGridFilter(o.value),
      })),
    );
  };

  // Library-scale as a compact dropdown (replaces the wide 3-item segmented that
  // overlapped the zoom-out button on narrow toolbars). Reuses the `.apg-menu`
  // popover, which supplies the menu role + checkmarks + arrow-key navigation.
  const scaleLabel = SCALE_OPTIONS.find((o) => o.value === libraryScale)?.label ?? 'All Photos';
  const openScaleMenu = (e: React.MouseEvent) => {
    const r = (e.currentTarget as HTMLElement).getBoundingClientRect();
    openContextMenu(
      r.left,
      r.bottom + 4,
      SCALE_OPTIONS.map((o) => ({
        label: o.label,
        checked: libraryScale === o.value,
        onClick: () => api.getState().setLibraryScale(o.value),
      })),
    );
  };

  const openMoreMenu = (e: React.MouseEvent) => {
    const r = (e.currentTarget as HTMLElement).getBoundingClientRect();
    const state = api.getState();
    const viewIds = mediaForView(state).map((m) => m.id);
    const allSelected = viewIds.length > 0 && viewIds.every((id) => state.selection.has(id));
    openContextMenu(r.left - 150, r.bottom + 4, [
      allSelected
        ? {
            label: 'Unselect All',
            icon: 'close',
            onClick: () => state.clearSelection(),
          }
        : {
            label: 'Select All',
            icon: 'check',
            onClick: () => state.selectMany(viewIds),
          },
      ...(features.import
        ? [{ label: 'Import…', icon: 'download' as const, onClick: () => openUploadModal(currentAlbumId) }]
        : []),
      ...(showThemeSwitcher
        ? [
            { type: 'separator' as const },
            { type: 'label' as const, label: 'Appearance' },
            { label: 'Light', icon: 'adjust' as const, checked: theme === 'light', onClick: () => state.setTheme('light') },
            { label: 'Dark', icon: 'adjust' as const, checked: theme === 'dark', onClick: () => state.setTheme('dark') },
            {
              label: 'Semi-Dark (Glass)',
              icon: 'adjust' as const,
              checked: theme === 'semi-dark',
              onClick: () => state.setTheme('semi-dark'),
            },
            { label: 'System', icon: 'adjust' as const, checked: theme === 'system', onClick: () => state.setTheme('system') },
          ]
        : []),
      { type: 'separator' as const },
      {
        label: state.lockConfigured ? 'Recently Deleted Lock…' : 'Lock Recently Deleted…',
        icon: state.lockConfigured ? 'lock' : 'unlock',
        onClick: () => openSecuritySettings(),
      },
      ...(view === 'recently-deleted'
        ? [
            { type: 'separator' as const },
            {
              label: 'Delete All',
              icon: 'trash' as const,
              danger: true,
              onClick: () =>
                confirmAction({
                  title: 'Delete All Items?',
                  message: 'These items will be permanently deleted. This cannot be undone.',
                  confirmLabel: 'Delete All',
                  danger: true,
                  onConfirm: () => api.getState().emptyTrash(),
                }),
            },
          ]
        : []),
    ]);
  };

  return (
    <div className="apg-toolbar">
      <button
        type="button"
        className="apg-iconbtn"
        aria-label="Toggle sidebar"
        onClick={() => api.getState().toggleSidebar()}
      >
        <Icon name="sidebar" />
      </button>
      <button
        type="button"
        className="apg-iconbtn apg-iconbtn--circle"
        aria-label="Back"
        disabled={!isAlbumish}
        onClick={() => api.getState().setView('library')}
      >
        <Icon name="chevron-left" size={18} />
      </button>

      {features.import ? (
        <button
          type="button"
          className="apg-iconbtn"
          aria-label="Add photos"
          onClick={() => openUploadModal(currentAlbumId)}
        >
          <Icon name="plus" />
        </button>
      ) : null}
      {features.camera ? (
        <button
          type="button"
          className="apg-iconbtn"
          aria-label="Open camera"
          onClick={() => api.getState().openCamera()}
        >
          <Icon name="camera" />
        </button>
      ) : null}

      {/* Center control (context dependent). Flanked by two flex spacers so it centres on
          wide toolbars and simply sits in flow (never overlapping the right group) when the
          toolbar is narrow — e.g. embedded, where the host + gallery sidebars eat the width. */}
      <div className="apg-toolbar__spacer" />
      <div className="apg-toolbar__center">
        {view === 'library' || view === 'search' ? (
          <button
            type="button"
            className="apg-scalemenu"
            aria-haspopup="menu"
            aria-label={`Library scale: ${scaleLabel}`}
            onClick={openScaleMenu}
          >
            <span className="apg-scalemenu__label">{scaleLabel}</span>
            <Icon name="chevron-down" size={14} />
          </button>
        ) : view === 'map' ? (
          <Segmented<MapMode>
            value={mapMode}
            onChange={(v) => api.getState().setMapMode(v)}
            options={[
              { value: 'map', label: 'Map' },
              { value: 'satellite', label: 'Satellite' },
              { value: 'grid', label: 'Grid' },
            ]}
          />
        ) : null}
      </div>

      <div className="apg-toolbar__spacer" />

      {isGrid ? (
        <>
          <button
            type="button"
            className="apg-iconbtn"
            aria-label="Zoom out"
            disabled={zoomIndex === 0}
            onClick={() => api.getState().zoomOut()}
          >
            <Icon name="minus" />
          </button>
          <button
            type="button"
            className="apg-iconbtn"
            aria-label="Zoom in"
            disabled={zoomIndex === GRID_ZOOM_STEPS.length - 1}
            onClick={() => api.getState().zoomIn()}
          >
            <Icon name="plus" />
          </button>
          <button type="button" className="apg-iconbtn" aria-label="Filter" onClick={openFilterMenu}>
            <Icon name="filter" />
          </button>
        </>
      ) : null}

      {features.sharing && (selectionCount > 0 || view.startsWith('album:')) ? (
        <button
          type="button"
          className="apg-iconbtn"
          aria-label="Share"
          onClick={() =>
            openShareModal(
              [...api.getState().selection],
              view.startsWith('album:') ? view : undefined,
            )
          }
        >
          <Icon name="share" />
        </button>
      ) : null}

      <button type="button" className="apg-iconbtn" aria-label="More" onClick={openMoreMenu}>
        <Icon name="ellipsis" />
      </button>
      <button
        type="button"
        className={['apg-iconbtn', fullscreen ? 'apg-iconbtn--on' : ''].join(' ')}
        aria-label={fullscreen ? 'Exit full screen' : 'Enter full screen'}
        title={fullscreen ? 'Exit full screen' : 'Enter full screen'}
        aria-pressed={fullscreen}
        onClick={() => api.getState().toggleFullscreen()}
      >
        <Icon name={fullscreen ? 'minimize' : 'maximize'} />
      </button>
      <button
        type="button"
        className={['apg-iconbtn', infoOpen ? 'apg-iconbtn--on' : ''].join(' ')}
        aria-label="Info"
        aria-pressed={infoOpen}
        onClick={() => api.getState().toggleInfo()}
      >
        <Icon name="info" />
      </button>

      {aiStatus.running ? (
        <span
          className="apg-ai-status"
          title="Analyzing your library with AI"
          aria-live="polite"
        >
          <span className="apg-ai-spinner" aria-hidden="true" />
          {aiStatus.done}/{aiStatus.total}
        </span>
      ) : null}

      <div
        className={['apg-search', searchExpanded ? 'apg-search--expanded' : ''].join(' ')}
        onClick={() => setSearchExpanded(true)}
      >
        <Icon name="search" size={16} />
        <input
          aria-label="Search"
          // Discoverability only: `searchMedia` already matches objectLabels,
          // OCR text, tags, captions and place names.
          placeholder="Search photos, objects, text…"
          value={searchQuery}
          onFocus={() => setSearchExpanded(true)}
          onChange={(e) => {
            const q = e.target.value;
            api.getState().setSearch(q);
            api.getState().setView((q ? 'search' : 'library') as ViewId);
          }}
          onBlur={() => setTimeout(() => setSearchExpanded(false), 120)}
        />
        {searchExpanded && !searchQuery ? (
          <div className="apg-search__recents" role="listbox">
            <div className="apg-menu__label">Recents</div>
            {(
              [
                ['viewed', 'Recently Viewed'],
                ['edited', 'Recently Edited'],
                ['added', 'Recently Added'],
              ] as Array<['viewed' | 'edited' | 'added', string]>
            ).map(([key, label]) => (
              <button
                key={key}
                type="button"
                className="apg-menu__item"
                onMouseDown={(e) => {
                  e.preventDefault();
                  api.getState().setSearchPreset(key);
                  setSearchExpanded(false);
                }}
              >
                <span className="apg-menu__icon">
                  <Icon name="clock" size={15} />
                </span>
                {label}
              </button>
            ))}
          </div>
        ) : null}
      </div>
    </div>
  );
}
