import React from 'react';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import MenuItem from '@mui/material/MenuItem';
import Paper from '@mui/material/Paper';
import Slider from '@mui/material/Slider';
import Pagination from '@mui/material/Pagination';
import InputAdornment from '@mui/material/InputAdornment';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import type { SxProps, Theme } from '@mui/material/styles';
import { WizardLayout } from '../../templates/WizardLayout';
import { Card } from '../../atoms/Card';
import { Badge } from '../../atoms/Badge';
import { Collapse } from '../../atoms/Collapse';
import { Typography } from '../../atoms/Typography';
import { Divider } from '../../atoms/Divider';
import { Link } from '../../atoms/Link';

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

/** A coffin available for selection */
export interface Coffin {
  id: string;
  name: string;
  imageUrl: string;
  /** Additional images (handles, fixtures, interior) shown as thumbnails */
  thumbnails?: string[];
  price: number;
  category: string;
  isPopular?: boolean;
  /** Number of colour/finish variants available */
  colourCount?: number;
}

/** Filter category option (supports one level of subcategories) */
export interface CoffinCategory {
  value: string;
  label: string;
  /** Subcategories — shown when parent is selected */
  children?: CoffinCategory[];
}

/** Sort direction */
export type CoffinSortBy = 'popularity' | 'price_asc' | 'price_desc';

/** Form values for the coffins step */
export interface CoffinsStepValues {
  /** Active category filter */
  categoryFilter: string;
  /** Price range [min, max] for slider filter */
  priceRange: [number, number];
  /** Sort order */
  sortBy: CoffinSortBy;
  /** Current page (1-indexed) */
  page: number;
}

/** Props for the CoffinsStep page component */
export interface CoffinsStepProps {
  /** Current filter/sort values */
  values: CoffinsStepValues;
  /** Callback when any filter/sort value changes */
  onChange: (values: CoffinsStepValues) => void;
  /** Called when a coffin card is clicked — navigates to CoffinDetailsStep */
  onSelectCoffin: (coffinId: string) => void;
  /** Callback for back navigation */
  onBack?: () => void;
  /** Callback for save-and-exit */
  onSaveAndExit?: () => void;
  /** Available coffins (already filtered/sorted/paginated by parent) */
  coffins: Coffin[];
  /** Total count before pagination (for display) */
  totalCount?: number;
  /** Total pages */
  totalPages?: number;
  /** Category filter options */
  categories?: CoffinCategory[];
  /** Min price for the range slider */
  minPrice?: number;
  /** Max price for the range slider */
  maxPrice?: number;
  /** Package coffin allowance amount (shown in info bubble, omit if no allowance) */
  allowanceAmount?: number;
  /** Max coffins per page before pagination (default 20) */
  pageSize?: number;
  /** Whether this is a pre-planning flow */
  isPrePlanning?: boolean;
  /** Navigation bar */
  navigation?: React.ReactNode;
  /** Progress stepper */
  progressStepper?: React.ReactNode;
  /** Running total */
  runningTotal?: React.ReactNode;
  /** Hide the help bar */
  hideHelpBar?: boolean;
  /** MUI sx prop */
  sx?: SxProps<Theme>;
}

// ─── Category menu item style ───────────────────────────────────────────────

const categoryItemSx = (isActive: boolean): SxProps<Theme> => ({
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-between',
  width: '100%',
  textAlign: 'left',
  border: 'none',
  background: 'none',
  cursor: 'pointer',
  py: 0.75,
  px: 1.5,
  borderRadius: 1,
  fontSize: '0.875rem',
  fontWeight: isActive ? 600 : 400,
  color: isActive ? 'primary.main' : 'text.primary',
  bgcolor: isActive ? 'var(--fa-color-brand-50)' : 'transparent',
  '&:hover': {
    bgcolor: isActive ? 'var(--fa-color-brand-50)' : 'var(--fa-color-surface-subtle)',
  },
  fontFamily: 'inherit',
});

// ─── Coffin card with thumbnail hover ───────────────────────────────────────

const CoffinCard: React.FC<{
  coffin: Coffin;
  onClick: () => void;
}> = ({ coffin, onClick }) => {
  const [previewImage, setPreviewImage] = React.useState(coffin.imageUrl);

  const allImages = [coffin.imageUrl, ...(coffin.thumbnails || [])];
  const hasThumbnails = allImages.length > 1;

  return (
    <Card
      interactive
      padding="none"
      onClick={onClick}
      sx={{
        overflow: 'hidden',
        cursor: 'pointer',
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
      }}
    >
      {/* Main image on subtle background — handles white-bg product photos */}
      <Box
        sx={{
          position: 'relative',
          height: 180,
          bgcolor: 'var(--fa-color-surface-subtle)',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          p: 2,
          flexShrink: 0,
        }}
      >
        <Box
          component="img"
          src={previewImage}
          alt={coffin.name}
          sx={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
        />
        {coffin.isPopular && (
          <Box sx={{ position: 'absolute', top: 8, left: 8 }}>
            <Badge variant="soft" color="brand" aria-label="Most popular choice">
              Most Popular
            </Badge>
          </Box>
        )}
      </Box>

      {/* Thumbnail strip — hover swaps main preview */}
      {hasThumbnails && (
        <Box
          sx={{ display: 'flex', gap: 0.5, px: 2, pt: 1, flexShrink: 0 }}
          onMouseLeave={() => setPreviewImage(coffin.imageUrl)}
        >
          {allImages.map((img, i) => (
            <Box
              key={i}
              component="img"
              src={img}
              alt=""
              onMouseEnter={() => setPreviewImage(img)}
              sx={{
                width: 48,
                height: 36,
                objectFit: 'cover',
                borderRadius: 0.5,
                border: 2,
                borderColor: previewImage === img ? 'primary.main' : 'transparent',
                opacity: previewImage === img ? 1 : 0.7,
                transition: 'border-color 0.15s, opacity 0.15s',
                '&:hover': { opacity: 1 },
              }}
            />
          ))}
        </Box>
      )}

      {/* Content — flex: 1 ensures all cards are the same height */}
      <Box
        sx={{ p: 2, pt: hasThumbnails ? 1 : 2, flex: 1, display: 'flex', flexDirection: 'column' }}
      >
        <Typography variant="h6" maxLines={2} sx={{ mb: 0.5 }}>
          {coffin.name}
        </Typography>
        <Typography variant="h6" color="primary">
          ${coffin.price.toLocaleString('en-AU')}
        </Typography>
        {coffin.colourCount != null && coffin.colourCount > 0 && (
          <Typography
            variant="caption"
            color="text.secondary"
            sx={{ mt: 'auto', pt: 0.5, display: 'block' }}
          >
            {coffin.colourCount} Colour option{coffin.colourCount !== 1 ? 's' : ''} available
          </Typography>
        )}
      </Box>
    </Card>
  );
};

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

/**
 * Step 10 — Coffin browsing for the FA arrangement wizard.
 *
 * Grid-sidebar layout: filter sidebar (left, stacked on mobile) + coffin
 * card grid (right). Both panels scroll independently on desktop; sidebar
 * scrollbar appears on hover.
 *
 * Clicking a coffin card navigates to CoffinDetailsStep — no Continue
 * button. Sidebar contains heading, allowance info, category menu with
 * expandable subcategories, price range slider with editable inputs,
 * sort control, and save-and-exit link.
 *
 * Cards show product image on subtle background (for white-bg photos),
 * thumbnail strip with hover preview, name, price, and colour count.
 * All cards are equal height regardless of thumbnail/colour presence.
 *
 * Uses Australian terminology: "coffin" not "casket".
 *
 * Pure presentation component — props in, callbacks out.
 * Filtering, sorting, and pagination logic handled by parent.
 *
 * Spec: documentation/steps/steps/10_coffins.yaml
 */
export const CoffinsStep: React.FC<CoffinsStepProps> = ({
  values,
  onChange,
  onSelectCoffin,
  onBack,
  onSaveAndExit,
  coffins,
  totalCount,
  totalPages = 1,
  categories = [
    { value: 'all', label: 'All' },
    {
      value: 'solid_timber',
      label: 'Solid Timber',
      children: [
        { value: 'cedar', label: 'Cedar' },
        { value: 'oak', label: 'Oak' },
        { value: 'mahogany', label: 'Mahogany' },
        { value: 'teak', label: 'Teak' },
      ],
    },
    {
      value: 'custom_board',
      label: 'Custom Board',
      children: [
        { value: 'printed', label: 'Printed' },
        { value: 'painted', label: 'Painted' },
      ],
    },
    { value: 'environmental', label: 'Environmental' },
    { value: 'designer', label: 'Designer' },
    { value: 'protective_metal', label: 'Protective Metal' },
  ],
  minPrice = 0,
  maxPrice = 15000,
  allowanceAmount,
  pageSize = 20,
  isPrePlanning = false,
  navigation,
  progressStepper,
  runningTotal,
  hideHelpBar,
  sx,
}) => {
  // Cap displayed coffins to pageSize (default 20 per page)
  const visibleCoffins = coffins.slice(0, pageSize);
  const displayCount = totalCount ?? coffins.length;
  const derivedTotalPages = totalPages > 1 ? totalPages : Math.ceil(coffins.length / pageSize);

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

  // Sync local state when the slider (or clear) changes the value
  const rangeMin = values.priceRange[0];
  const rangeMax = values.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] !== values.priceRange[0] || newRange[1] !== values.priceRange[1]) {
      onChange({ ...values, priceRange: newRange, page: 1 });
    }
  };

  // ─── Derived state ───
  const hasActiveFilters =
    values.categoryFilter !== 'all' ||
    values.priceRange[0] !== minPrice ||
    values.priceRange[1] !== maxPrice;

  // Determine which parent category is expanded (if filter matches parent or child)
  const expandedParent =
    categories.find(
      (cat) =>
        cat.value === values.categoryFilter ||
        cat.children?.some((child) => child.value === values.categoryFilter),
    )?.value ?? null;

  const handleClearFilters = () => {
    onChange({
      ...values,
      categoryFilter: 'all',
      priceRange: [minPrice, maxPrice],
      page: 1,
    });
  };

  return (
    <WizardLayout
      variant="grid-sidebar"
      navigation={navigation}
      progressStepper={progressStepper}
      runningTotal={runningTotal}
      showBackLink={!!onBack}
      backLabel="Back"
      onBack={onBack}
      hideHelpBar={hideHelpBar}
      sx={sx}
      secondaryPanel={
        /* ─── Grid area (right panel) ─── */
        <Box>
          {/* Results count */}
          <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }} aria-live="polite">
            Showing {displayCount} coffin{displayCount !== 1 ? 's' : ''}
          </Typography>

          {/* Coffin card grid */}
          <Box
            role="list"
            aria-label="Available coffins"
            sx={{
              display: 'grid',
              gridTemplateColumns: {
                xs: '1fr',
                sm: 'repeat(2, 1fr)',
                md: 'repeat(3, 1fr)',
              },
              gap: 2,
              mb: 3,
            }}
          >
            {visibleCoffins.map((coffin) => (
              <Box key={coffin.id} role="listitem">
                <CoffinCard coffin={coffin} onClick={() => onSelectCoffin(coffin.id)} />
              </Box>
            ))}

            {visibleCoffins.length === 0 && (
              <Box sx={{ py: 6, textAlign: 'center', gridColumn: '1 / -1' }}>
                <Typography variant="body1" color="text.secondary" sx={{ mb: 1 }}>
                  No coffins match your selected filters.
                </Typography>
                <Typography variant="body2" color="text.secondary">
                  Try adjusting the category or price range.
                </Typography>
              </Box>
            )}
          </Box>

          {/* Pagination */}
          {derivedTotalPages > 1 && (
            <Box sx={{ display: 'flex', justifyContent: 'center' }}>
              <Pagination
                count={derivedTotalPages}
                page={values.page}
                onChange={(_, page) => onChange({ ...values, page })}
                color="primary"
              />
            </Box>
          )}
        </Box>
      }
    >
      {/* ─── Sidebar (left panel) ─── */}

      {/* Heading — matches VenueStep / ProvidersStep list layout */}
      <Typography variant="h4" component="h1" sx={{ mb: 0.5, pt: 2 }} tabIndex={-1}>
        Choose a coffin
      </Typography>
      <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
        {isPrePlanning
          ? 'Browse the range to get an idea of styles and pricing.'
          : 'Browse our selection of bespoke designer coffins.'}
      </Typography>

      {/* Allowance info bubble */}
      {allowanceAmount != null && (
        <Paper
          variant="outlined"
          sx={{
            p: 2,
            mb: 3,
            display: 'flex',
            gap: 1.5,
            alignItems: 'flex-start',
            bgcolor: 'var(--fa-color-surface-warm)',
            borderColor: 'var(--fa-color-brand-200)',
          }}
        >
          <InfoOutlinedIcon
            sx={{ fontSize: 20, color: 'var(--fa-color-brand-500)', flexShrink: 0, mt: 0.25 }}
          />
          <Typography variant="body2">
            Your package includes a <strong>${allowanceAmount.toLocaleString('en-AU')}</strong>{' '}
            allowance for coffins which will be applied to your order after you have made a
            selection.
          </Typography>
        </Paper>
      )}

      <Divider sx={{ mb: 3 }} />

      {/* ─── Categories menu — single-select with expandable subcategories ─── */}
      <Typography variant="h6" sx={{ mb: 1.5 }}>
        Categories
      </Typography>
      <Box component="nav" aria-label="Filter by category" sx={{ mb: 3 }}>
        {categories.map((cat) => {
          const isParentActive =
            cat.value === values.categoryFilter ||
            cat.children?.some((child) => child.value === values.categoryFilter);
          const isExactActive = cat.value === values.categoryFilter;
          const isExpanded = expandedParent === cat.value;

          return (
            <React.Fragment key={cat.value}>
              {/* Parent category */}
              <Box
                component="button"
                type="button"
                onClick={() => onChange({ ...values, categoryFilter: cat.value, page: 1 })}
                sx={categoryItemSx(!!isExactActive)}
              >
                <span>{cat.label}</span>
                {cat.children && cat.children.length > 0 && (
                  <ExpandMoreIcon
                    sx={{
                      fontSize: 18,
                      color: isParentActive ? 'primary.main' : 'text.secondary',
                      transform: isExpanded ? 'rotate(0deg)' : 'rotate(-90deg)',
                      transition: 'transform 0.2s',
                    }}
                  />
                )}
              </Box>

              {/* Subcategories — expand when parent is active */}
              {cat.children && cat.children.length > 0 && (
                <Collapse in={isExpanded}>
                  <Box sx={{ pl: 2 }}>
                    {cat.children.map((child) => (
                      <Box
                        key={child.value}
                        component="button"
                        type="button"
                        onClick={() =>
                          onChange({ ...values, categoryFilter: child.value, page: 1 })
                        }
                        sx={categoryItemSx(child.value === values.categoryFilter)}
                      >
                        <span>{child.label}</span>
                      </Box>
                    ))}
                  </Box>
                </Collapse>
              )}
            </React.Fragment>
          );
        })}
      </Box>

      <Divider sx={{ mb: 3 }} />

      {/* ─── Price range slider with editable inputs ─── */}
      <Typography variant="h6" sx={{ mb: 1.5 }}>
        Price
      </Typography>
      <Box sx={{ px: 1, mb: 1.5 }}>
        <Slider
          value={values.priceRange}
          onChange={(_, newValue) =>
            onChange({ ...values, priceRange: newValue as [number, number], page: 1 })
          }
          min={minPrice}
          max={maxPrice}
          step={100}
          valueLabelDisplay="auto"
          valueLabelFormat={(v) => `$${v.toLocaleString('en-AU')}`}
          color="primary"
        />
      </Box>
      <Box sx={{ display: 'flex', gap: 1, mb: 3 }}>
        <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' }}
          sx={{ flex: 1 }}
        />
        <Typography variant="body2" color="text.secondary" sx={{ alignSelf: 'center' }}>
          –
        </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' }}
          sx={{ flex: 1 }}
        />
      </Box>

      <Divider sx={{ mb: 3 }} />

      {/* ─── Sort by ─── */}
      <Typography variant="h6" sx={{ mb: 2 }}>
        Sort by
      </Typography>
      <TextField
        select
        value={values.sortBy}
        onChange={(e) => onChange({ ...values, sortBy: e.target.value as CoffinSortBy })}
        fullWidth
        size="small"
      >
        <MenuItem value="popularity">Popularity</MenuItem>
        <MenuItem value="price_asc">Price: Low to High</MenuItem>
        <MenuItem value="price_desc">Price: High to Low</MenuItem>
      </TextField>

      {/* Clear filters — at bottom of sidebar, under sort */}
      {hasActiveFilters && (
        <>
          <Divider sx={{ my: 3 }} />
          <Link
            component="button"
            onClick={handleClearFilters}
            underline="hover"
            sx={{ fontSize: '0.875rem' }}
          >
            Clear all filters
          </Link>
        </>
      )}

      {/* Save and continue later — bottom of sidebar */}
      {onSaveAndExit && (
        <>
          <Divider sx={{ my: 3 }} />
          <Link
            component="button"
            onClick={onSaveAndExit}
            underline="hover"
            sx={{ fontSize: '0.875rem', color: 'text.secondary' }}
          >
            Save and continue later
          </Link>
        </>
      )}
    </WizardLayout>
  );
};

CoffinsStep.displayName = 'CoffinsStep';
export default CoffinsStep;
