import React from 'react';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import InputAdornment from '@mui/material/InputAdornment';
import Autocomplete from '@mui/material/Autocomplete';
import FormControlLabel from '@mui/material/FormControlLabel';
import Slider from '@mui/material/Slider';
import MenuItem from '@mui/material/MenuItem';
import Menu from '@mui/material/Menu';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import ToggleButton from '@mui/material/ToggleButton';
import SwapVertIcon from '@mui/icons-material/SwapVert';
import SearchIcon from '@mui/icons-material/Search';
import ViewListOutlinedIcon from '@mui/icons-material/ViewListOutlined';
import MapOutlinedIcon from '@mui/icons-material/MapOutlined';
import LocationOnOutlinedIcon from '@mui/icons-material/LocationOnOutlined';
import type { SxProps, Theme } from '@mui/material/styles';
import { WizardLayout } from '../../templates/WizardLayout';
import { ProviderCard } from '../../molecules/ProviderCard';
import { FilterPanel } from '../../molecules/FilterPanel';
import { Button } from '../../atoms/Button';
import { Chip } from '../../atoms/Chip';
import { IconButton } from '../../atoms/IconButton';
import { Switch } from '../../atoms/Switch';
import { Typography } from '../../atoms/Typography';
import { Divider } from '../../atoms/Divider';

// ─── Types ───────────────────────────────────────────────────────────────────

/** Provider data for display in the list */
export interface ProviderData {
  /** Unique provider ID (funeralBrandID) */
  id: string;
  /** Provider display name */
  name: string;
  /** Location text (suburb, city) */
  location: string;
  /** Whether this is a verified/trusted partner */
  verified?: boolean;
  /** Hero image URL */
  imageUrl?: string;
  /** Provider logo URL */
  logoUrl?: string;
  /** Average rating (e.g. 4.8) */
  rating?: number;
  /** Number of reviews */
  reviewCount?: number;
  /** Starting price in dollars */
  startingPrice?: number;
  /** Distance from user in km */
  distanceKm?: number;
  /** Brief description */
  description?: string;
  /** Geographic coordinates for map display */
  coords?: { lat: number; lng: number };
}

/** A funeral type option for the filter */
export interface FuneralTypeOption {
  /** Machine-readable value (e.g. "service_and_cremation") */
  value: string;
  /** Human-readable label (e.g. "Service & Cremation") */
  label: string;
}

/** Structured filter state for the providers list */
export interface ProviderFilterValues {
  /** Selected service tradition (null = any) */
  tradition: string | null;
  /** Selected funeral type values (empty = all) */
  funeralTypes: string[];
  /** Show only verified providers */
  verifiedOnly: boolean;
  /** Show only providers offering online arrangements */
  onlineArrangements: boolean;
  /** Price range [min, max] */
  priceRange: [number, number];
}

/** Sort options for the provider list */
export type ProviderSortBy = 'recommended' | 'nearest' | 'price_low' | 'price_high';

/** View mode for the listing */
export type ListViewMode = 'list' | 'map';

/** Props for the ProvidersStep page component */
export interface ProvidersStepProps {
  /** List of providers to display */
  providers: ProviderData[];
  /** Callback when a provider card is clicked — triggers navigation (D-D) */
  onSelectProvider: (id: string) => void;
  /** Search query value */
  searchQuery: string;
  /** Callback when search query changes */
  onSearchChange: (query: string) => void;
  /** Callback when search is submitted */
  onSearch?: (query: string) => void;
  /** Current filter state */
  filterValues: ProviderFilterValues;
  /** Callback when any filter changes */
  onFilterChange: (values: ProviderFilterValues) => void;
  /** Available service tradition options for the autocomplete */
  traditionOptions?: string[];
  /** Available funeral type options */
  funeralTypeOptions?: FuneralTypeOption[];
  /** Minimum price for the slider (default 0) */
  minPrice?: number;
  /** Maximum price for the slider (default 15000) */
  maxPrice?: number;
  /** Current sort order */
  sortBy?: ProviderSortBy;
  /** Callback when sort order changes */
  onSortChange?: (sort: ProviderSortBy) => void;
  /** Current view mode */
  viewMode?: ListViewMode;
  /** Callback when view mode changes */
  onViewModeChange?: (mode: ListViewMode) => void;
  /** Callback for the Back button */
  onBack: () => void;
  /** Map panel content — slot for future map integration */
  mapPanel?: React.ReactNode;
  /** Navigation bar — passed through to WizardLayout */
  navigation?: React.ReactNode;
  /** Progress stepper — passed through to WizardLayout */
  progressStepper?: React.ReactNode;
  /** Running total — passed through to WizardLayout */
  runningTotal?: React.ReactNode;
  /** Whether this is a pre-planning flow (shows softer copy) */
  isPrePlanning?: boolean;
  /** MUI sx prop for the root */
  sx?: SxProps<Theme>;
}

// ─── Defaults ────────────────────────────────────────────────────────────────

const DEFAULT_TRADITIONS = [
  'None',
  'Anglican',
  "Bahá'í",
  'Baptist',
  'Buddhist',
  'Catholic',
  'Eastern Orthodox',
  'Hindu',
  'Humanist',
  'Indigenous Australian',
  'Jewish',
  'Lutheran',
  'Methodist',
  'Muslim',
  'Non-religious',
  'Pentecostal',
  'Presbyterian',
  'Salvation Army',
  'Secular',
  'Sikh',
  'Uniting Church',
];

const DEFAULT_FUNERAL_TYPES: FuneralTypeOption[] = [
  { value: 'service_and_cremation', label: 'Service & Cremation' },
  { value: 'service_and_burial', label: 'Service & Burial' },
  { value: 'cremation_only', label: 'Cremation Only' },
  { value: 'graveside_burial', label: 'Graveside Burial' },
  { value: 'water_cremation', label: 'Water Cremation' },
  { value: 'burial_only', label: 'Burial Only' },
];

const SORT_OPTIONS: { value: ProviderSortBy; label: string }[] = [
  { value: 'recommended', label: 'Recommended' },
  { value: 'nearest', label: 'Nearest' },
  { value: 'price_low', label: 'Price low to high' },
  { value: 'price_high', label: 'Price high to low' },
];

export const EMPTY_FILTER_VALUES: ProviderFilterValues = {
  tradition: null,
  funeralTypes: [],
  verifiedOnly: false,
  onlineArrangements: false,
  priceRange: [0, 15000],
};

// ─── Shared styles ───────────────────────────────────────────────────────────

/** Section heading inside the filter panel */
const sectionHeadingSx = {
  mb: 1.5,
  display: 'block',
  fontWeight: 600,
  color: 'text.primary',
} as const;

/** Wrapping chip row */
const chipWrapSx = {
  display: 'flex',
  flexWrap: 'wrap',
  gap: 1,
} as const;

// ─── Component ───────────────────────────────────────────────────────────────

/**
 * Step 2 — Provider selection page for the FA arrangement wizard.
 *
 * List + Map split layout. Left panel shows a scrollable list of
 * provider cards with search and filter button. Right panel is a
 * slot for future map integration.
 *
 * Click-to-navigate (D-D): clicking a provider card triggers
 * navigation directly — no selection state or Continue button.
 *
 * Filters: location (chip + search), service tradition (autocomplete),
 * funeral type (horizontal scroll chips), verified only (switch),
 * online arrangements (switch), price range (slider + compact inputs).
 *
 * Pure presentation component — props in, callbacks out.
 *
 * Spec: documentation/steps/steps/02_providers.yaml
 */
export const ProvidersStep: React.FC<ProvidersStepProps> = ({
  providers,
  onSelectProvider,
  searchQuery,
  onSearchChange,
  onSearch,
  filterValues,
  onFilterChange,
  traditionOptions = DEFAULT_TRADITIONS,
  funeralTypeOptions = DEFAULT_FUNERAL_TYPES,
  minPrice = 0,
  maxPrice = 15000,
  sortBy = 'recommended',
  onSortChange,
  viewMode = 'list',
  onViewModeChange,
  onBack,
  mapPanel,
  navigation,
  progressStepper,
  runningTotal,
  isPrePlanning = false,
  sx,
}) => {
  const subheading = isPrePlanning
    ? 'Take your time exploring providers. You can always come back and choose a different one.'
    : 'These providers are near your location. Each has their own packages and pricing.';

  // ─── Local state ───
  const [sortAnchor, setSortAnchor] = React.useState<null | HTMLElement>(null);
  // Draft value for the sticky search input — only committed (promoted to a
  // chip) on Enter or when the search button is clicked. searchQuery is the
  // committed filter value; the draft lives here until the user confirms.
  const [searchDraft, setSearchDraft] = React.useState('');

  const commitSearch = (next: string) => {
    const trimmed = next.trim();
    if (!trimmed) return;
    onSearchChange(trimmed);
    onSearch?.(trimmed);
    setSearchDraft('');
  };

  // ─── Price input local state (commits on blur / Enter) ───
  const [priceMinInput, setPriceMinInput] = React.useState(String(filterValues.priceRange[0]));
  const [priceMaxInput, setPriceMaxInput] = React.useState(String(filterValues.priceRange[1]));

  // Sync local state when slider (or clear) changes the value
  const rangeMin = filterValues.priceRange[0];
  const rangeMax = filterValues.priceRange[1];
  React.useEffect(() => {
    setPriceMinInput(String(rangeMin));
    setPriceMaxInput(String(rangeMax));
  }, [rangeMin, rangeMax]);

  const commitPriceRange = () => {
    let lo = parseInt(priceMinInput, 10);
    let hi = parseInt(priceMaxInput, 10);
    if (isNaN(lo)) lo = minPrice;
    if (isNaN(hi)) hi = maxPrice;
    lo = Math.max(minPrice, Math.min(lo, maxPrice));
    hi = Math.max(minPrice, Math.min(hi, maxPrice));
    if (lo > hi) [lo, hi] = [hi, lo];
    const newRange: [number, number] = [lo, hi];
    if (newRange[0] !== filterValues.priceRange[0] || newRange[1] !== filterValues.priceRange[1]) {
      onFilterChange({ ...filterValues, priceRange: newRange });
    }
  };

  // ─── Active filter count ───
  const activeCount =
    (searchQuery.trim() ? 1 : 0) +
    (filterValues.tradition ? 1 : 0) +
    filterValues.funeralTypes.length +
    (filterValues.verifiedOnly ? 1 : 0) +
    (filterValues.onlineArrangements ? 1 : 0) +
    (filterValues.priceRange[0] !== minPrice || filterValues.priceRange[1] !== maxPrice ? 1 : 0);

  const handleClear = () => {
    onSearchChange('');
    onFilterChange({
      ...EMPTY_FILTER_VALUES,
      priceRange: [minPrice, maxPrice],
    });
  };

  const handleFuneralTypeToggle = (value: string) => {
    const current = filterValues.funeralTypes;
    const next = current.includes(value) ? current.filter((v) => v !== value) : [...current, value];
    onFilterChange({ ...filterValues, funeralTypes: next });
  };

  return (
    <WizardLayout
      variant="list-map"
      navigation={navigation}
      progressStepper={progressStepper}
      runningTotal={runningTotal}
      showBackLink
      backLabel="Back"
      onBack={onBack}
      sx={sx}
      secondaryPanel={
        <Box sx={{ position: 'relative', flex: 1, display: 'flex' }}>
          {/* Floating view toggle */}
          <ToggleButtonGroup
            value={viewMode}
            exclusive
            onChange={(_, val) => val && onViewModeChange?.(val as ListViewMode)}
            size="small"
            aria-label="View mode"
            sx={{
              position: 'absolute',
              top: 12,
              left: 12,
              zIndex: 1,
              bgcolor: 'background.paper',
              boxShadow: 'var(--fa-shadow-md)',
              borderRadius: 1,
              '& .MuiToggleButton-root': {
                px: 1.5,
                py: 0.5,
                fontSize: '0.75rem',
                fontWeight: 500,
                gap: 0.5,
                border: '1px solid',
                borderColor: 'divider',
                textTransform: 'none',
                '&.Mui-selected': {
                  bgcolor: 'var(--fa-color-brand-100)',
                  color: 'primary.main',
                  borderColor: 'primary.main',
                  '&:hover': { bgcolor: 'var(--fa-color-brand-200)' },
                },
              },
            }}
          >
            <ToggleButton value="list" aria-label="List view">
              <ViewListOutlinedIcon sx={{ fontSize: 16 }} />
              List
            </ToggleButton>
            <ToggleButton value="map" aria-label="Map view">
              <MapOutlinedIcon sx={{ fontSize: 16 }} />
              Map
            </ToggleButton>
          </ToggleButtonGroup>

          {/* Map content */}
          {mapPanel || (
            <Box
              sx={{
                flex: 1,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                bgcolor: 'var(--fa-color-surface-cool)',
                borderLeft: '1px solid',
                borderColor: 'divider',
              }}
            >
              <Typography variant="body1" color="text.secondary">
                Map coming soon
              </Typography>
            </Box>
          )}
        </Box>
      }
    >
      {/* Heading — scrolls with listings */}
      <Typography variant="h4" component="h1" sx={{ mb: 0.5, pt: 2 }} tabIndex={-1}>
        Find a funeral director
      </Typography>
      <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
        {subheading}
      </Typography>

      {/* Sticky controls — search + filters pinned while listings scroll */}
      <Box
        sx={{
          position: 'sticky',
          top: 0,
          zIndex: 1,
          bgcolor: 'background.default',
          pt: 3,
          pb: 1.5,
          mx: { xs: -2, md: -3 },
          px: { xs: 2, md: 3 },
          borderBottom: '1px solid',
          borderColor: 'divider',
        }}
      >
        {/* Location search — committed location renders as a chip inside the
            input. Typing produces a draft; Enter or the search button commit
            it. Deleting the chip clears the committed filter. */}
        <Autocomplete
          multiple
          freeSolo
          options={[]}
          forcePopupIcon={false}
          clearIcon={null}
          value={searchQuery.trim() ? [searchQuery.trim()] : []}
          inputValue={searchDraft}
          onInputChange={(_, newDraft, reason) => {
            // Ignore the 'reset' input-change Autocomplete fires after a value
            // commit (it echoes the committed value back into the input and
            // would otherwise re-populate the draft we just cleared).
            if (reason === 'reset') return;
            setSearchDraft(newDraft);
          }}
          onChange={(_, newValue) => {
            if (newValue.length === 0) {
              // Chip removed — clear the committed filter
              onSearchChange('');
              return;
            }
            // Commit the most-recent entry (cap at 1 location)
            const last = newValue[newValue.length - 1];
            if (typeof last === 'string') commitSearch(last);
          }}
          renderTags={(value, getTagProps) =>
            value.map((option, index) => {
              const { key, ...chipProps } = getTagProps({ index });
              return (
                <Chip
                  key={key}
                  label={option}
                  size="small"
                  aria-label={`Current location: ${option}. Press delete to clear.`}
                  {...chipProps}
                />
              );
            })
          }
          renderInput={(params) => (
            <TextField
              {...params}
              placeholder={searchQuery.trim() ? '' : 'Search a town or suburb...'}
              size="small"
              inputProps={{
                ...params.inputProps,
                'aria-label': 'Search providers by town or suburb',
              }}
              InputProps={{
                ...params.InputProps,
                startAdornment: (
                  <>
                    <InputAdornment position="start" sx={{ ml: 0.5, mr: 0.5 }}>
                      <LocationOnOutlinedIcon sx={{ color: 'text.secondary', fontSize: 20 }} />
                    </InputAdornment>
                    {params.InputProps.startAdornment}
                  </>
                ),
                endAdornment: (
                  <InputAdornment position="end" sx={{ mr: 0.5 }}>
                    <IconButton
                      aria-label="Search"
                      onClick={() => commitSearch(searchDraft)}
                      sx={{
                        width: 28,
                        height: 28,
                        borderRadius: '50%',
                        bgcolor: 'primary.main',
                        color: 'primary.contrastText',
                        '&:hover': { bgcolor: 'primary.dark' },
                        '&:focus-visible': { outline: 'none' },
                      }}
                    >
                      <SearchIcon sx={{ fontSize: 16 }} />
                    </IconButton>
                  </InputAdornment>
                ),
              }}
            />
          )}
          sx={{
            mb: 1.5,
            // Kill the custom brand focus ring + border colour change on focus
            '& .MuiOutlinedInput-root.Mui-focused': {
              boxShadow: 'none',
              '& .MuiOutlinedInput-notchedOutline': {
                borderColor: 'var(--fa-color-neutral-300)',
                borderWidth: 1,
              },
            },
          }}
        />

        {/* Control bar — filters + sort */}
        <Box
          sx={{
            display: 'flex',
            alignItems: 'center',
            gap: 1,
          }}
        >
          {/* Filters */}
          <FilterPanel
            activeCount={activeCount}
            onClear={handleClear}
            sx={{ '& .MuiButton-root:focus-visible': { outline: 'none' } }}
          >
            {/* ── Location ── */}
            <Box>
              <Typography variant="labelLg" sx={sectionHeadingSx}>
                Location
              </Typography>
              <Autocomplete
                multiple
                freeSolo
                value={searchQuery.trim() ? [searchQuery.trim()] : []}
                onChange={(_, newValue) => {
                  // Take the last entered value as the active search
                  const last = newValue[newValue.length - 1] ?? '';
                  onSearchChange(typeof last === 'string' ? last : '');
                }}
                options={[]}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    placeholder={searchQuery.trim() ? '' : 'Search a town or suburb...'}
                    size="small"
                    InputProps={{
                      ...params.InputProps,
                      startAdornment: (
                        <>
                          <InputAdornment position="start" sx={{ ml: 0.5 }}>
                            <LocationOnOutlinedIcon
                              sx={{ color: 'text.secondary', fontSize: 18 }}
                            />
                          </InputAdornment>
                          {params.InputProps.startAdornment}
                        </>
                      ),
                    }}
                  />
                )}
                size="small"
              />
            </Box>

            <Divider />

            {/* ── Service tradition ── */}
            <Box>
              <Typography variant="labelLg" sx={sectionHeadingSx}>
                Service tradition
              </Typography>
              <Autocomplete
                value={filterValues.tradition}
                onChange={(_, newValue) => onFilterChange({ ...filterValues, tradition: newValue })}
                options={traditionOptions}
                renderInput={(params) => (
                  <TextField {...params} placeholder="Search traditions..." size="small" />
                )}
                clearOnEscape
                size="small"
              />
            </Box>

            <Divider />

            {/* ── Funeral type ── */}
            <Box>
              <Typography variant="labelLg" sx={sectionHeadingSx}>
                Funeral type
              </Typography>
              <Box sx={chipWrapSx}>
                {funeralTypeOptions.map((option) => (
                  <Chip
                    key={option.value}
                    label={option.label}
                    selected={filterValues.funeralTypes.includes(option.value)}
                    onClick={() => handleFuneralTypeToggle(option.value)}
                    variant="outlined"
                    size="small"
                  />
                ))}
              </Box>
            </Box>

            <Divider />

            {/* ── Provider features ── */}
            <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
              <FormControlLabel
                control={
                  <Switch
                    checked={filterValues.verifiedOnly}
                    onChange={(_, checked) =>
                      onFilterChange({ ...filterValues, verifiedOnly: checked })
                    }
                  />
                }
                label="Verified providers only"
                sx={{ mx: 0 }}
              />
              <FormControlLabel
                control={
                  <Switch
                    checked={filterValues.onlineArrangements}
                    onChange={(_, checked) =>
                      onFilterChange({ ...filterValues, onlineArrangements: checked })
                    }
                  />
                }
                label="Online arrangements available"
                sx={{ mx: 0 }}
              />
            </Box>

            <Divider />

            {/* ── Price range ── */}
            <Box>
              <Typography variant="labelLg" sx={sectionHeadingSx}>
                Price range
              </Typography>
              <Box sx={{ px: 2.5, mb: 1 }}>
                <Slider
                  value={filterValues.priceRange}
                  onChange={(_, newValue) =>
                    onFilterChange({
                      ...filterValues,
                      priceRange: newValue as [number, number],
                    })
                  }
                  min={minPrice}
                  max={maxPrice}
                  step={100}
                  valueLabelDisplay="auto"
                  valueLabelFormat={(v) => `$${v.toLocaleString('en-AU')}`}
                  color="primary"
                />
              </Box>
              <Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
                <TextField
                  size="small"
                  value={priceMinInput}
                  onChange={(e) => setPriceMinInput(e.target.value.replace(/[^0-9]/g, ''))}
                  onBlur={commitPriceRange}
                  onKeyDown={(e) => e.key === 'Enter' && commitPriceRange()}
                  InputProps={{
                    startAdornment: <InputAdornment position="start">$</InputAdornment>,
                  }}
                  inputProps={{
                    inputMode: 'numeric',
                    'aria-label': 'Minimum price',
                    style: { padding: '6px 0' },
                  }}
                  sx={{ flex: 1, '& .MuiOutlinedInput-root': { fontSize: '0.875rem' } }}
                />
                <Typography variant="caption" color="text.secondary">
                  –
                </Typography>
                <TextField
                  size="small"
                  value={priceMaxInput}
                  onChange={(e) => setPriceMaxInput(e.target.value.replace(/[^0-9]/g, ''))}
                  onBlur={commitPriceRange}
                  onKeyDown={(e) => e.key === 'Enter' && commitPriceRange()}
                  InputProps={{
                    startAdornment: <InputAdornment position="start">$</InputAdornment>,
                  }}
                  inputProps={{
                    inputMode: 'numeric',
                    'aria-label': 'Maximum price',
                    style: { padding: '6px 0' },
                  }}
                  sx={{ flex: 1, '& .MuiOutlinedInput-root': { fontSize: '0.875rem' } }}
                />
              </Box>
            </Box>
          </FilterPanel>

          {/* Sort — compact menu button, pushed right */}
          <Box sx={{ ml: 'auto' }}>
            <Button
              variant="outlined"
              color="secondary"
              size="small"
              startIcon={<SwapVertIcon sx={{ fontSize: 16 }} />}
              onClick={(e) => setSortAnchor(e.currentTarget)}
              aria-haspopup="listbox"
              aria-label={`Sort by ${SORT_OPTIONS.find((o) => o.value === sortBy)?.label ?? 'Recommended'}`}
              sx={{ textTransform: 'none', '&:focus-visible': { outline: 'none' } }}
            >
              <Box component="span" sx={{ color: 'text.secondary', fontWeight: 400, mr: 0.5 }}>
                Sort:
              </Box>
              {SORT_OPTIONS.find((o) => o.value === sortBy)?.label ?? 'Recommended'}
            </Button>
            <Menu
              anchorEl={sortAnchor}
              open={Boolean(sortAnchor)}
              onClose={() => setSortAnchor(null)}
              anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
              transformOrigin={{ vertical: 'top', horizontal: 'right' }}
            >
              {SORT_OPTIONS.map((opt) => (
                <MenuItem
                  key={opt.value}
                  selected={opt.value === sortBy}
                  onClick={() => {
                    onSortChange?.(opt.value);
                    setSortAnchor(null);
                  }}
                  sx={{ fontSize: '0.813rem' }}
                >
                  {opt.label}
                </MenuItem>
              ))}
            </Menu>
          </Box>
        </Box>

        {/* Results count — below controls */}
        <Typography
          variant="caption"
          color="text.secondary"
          sx={{ mt: 3, display: 'block' }}
          aria-live="polite"
        >
          <Box component="span" sx={{ fontWeight: 600, color: 'text.primary' }}>
            {providers.length}
          </Box>{' '}
          provider{providers.length !== 1 ? 's' : ''} found
        </Typography>
      </Box>

      {/* Provider list — click-to-navigate (D-D) */}
      <Box
        role="list"
        aria-label="Funeral providers"
        sx={{
          display: 'flex',
          flexDirection: 'column',
          gap: 2,
          pb: 3,
          pt: 2,
          px: { xs: 2, md: 3 },
          mx: { xs: -2, md: -3 },
          bgcolor: 'var(--fa-color-surface-subtle)',
        }}
      >
        {providers.map((provider) => (
          <ProviderCard
            key={provider.id}
            name={provider.name}
            location={provider.location}
            verified={provider.verified}
            imageUrl={provider.imageUrl}
            logoUrl={provider.logoUrl}
            rating={provider.rating}
            reviewCount={provider.reviewCount}
            startingPrice={provider.startingPrice}
            onClick={() => onSelectProvider(provider.id)}
            aria-label={`${provider.name}, ${provider.location}${provider.rating ? `, rated ${provider.rating}` : ''}${provider.startingPrice ? `, from $${provider.startingPrice}` : ''}`}
          />
        ))}

        {providers.length === 0 && (
          <Box sx={{ py: 6, textAlign: 'center' }}>
            <Typography variant="body1" color="text.secondary" sx={{ mb: 1 }}>
              No providers found matching your search.
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Try adjusting your search or clearing filters.
            </Typography>
          </Box>
        )}
      </Box>
    </WizardLayout>
  );
};

ProvidersStep.displayName = 'ProvidersStep';
export default ProvidersStep;
