import React from 'react';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import Slide from '@mui/material/Slide';
import useMediaQuery from '@mui/material/useMediaQuery';
import IconButton from '@mui/material/IconButton';
import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded';
import ChevronLeftRoundedIcon from '@mui/icons-material/ChevronLeftRounded';
import { useTheme, type SxProps, type Theme } from '@mui/material/styles';
import { Typography } from '../../atoms/Typography';
import { Button } from '../../atoms/Button';
import { Badge } from '../../atoms/Badge';

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

/** A package in the comparison basket */
export interface CompareBarPackage {
  /** Unique package ID */
  id: string;
  /** Package display name */
  name: string;
  /** Provider name */
  providerName: string;
}

/** Props for the CompareBar molecule */
export interface CompareBarProps {
  /** Packages currently in the comparison basket (max 3 user-selected) */
  packages: CompareBarPackage[];
  /** Called when user clicks "Compare" CTA */
  onCompare: () => void;
  /** Error/status message shown inline (e.g. "Maximum 3 packages") */
  error?: string;
  /** MUI sx prop for the root wrapper */
  sx?: SxProps<Theme>;
}

// ─── Constants ──────────────────────────────────────────────────────────────

/** How long the bar stays expanded after a new package is added while
 *  collapsed. Long enough to read, short enough not to obstruct. */
const PEEK_DURATION_MS = 3000;
/** Middle-content expand/collapse duration (width + opacity). */
const COLLAPSE_MS = 300;

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

/**
 * Floating comparison basket pill for the FA design system.
 *
 * Shows a fraction badge (1/3, 2/3, 3/3), contextual copy, and a Compare CTA.
 * Present on both ProvidersStep and PackagesStep.
 *
 * **Mobile collapse** (xs only): users can tap a right-chevron to retract
 * the pill to the right edge — the middle content (status text + Compare
 * button) animates to width:0 while the pill stays anchored at the same
 * right offset, so the whole thing appears to shrink into the corner as
 * one unit rather than two separate elements. Tap again to expand. When
 * a new package is added while collapsed, the bar auto-peeks for
 * `PEEK_DURATION_MS` so the user sees the tally update, then re-collapses.
 *
 * Desktop (md+) stays expanded — there's plenty of space, and the
 * collapse chevron is not rendered.
 *
 * Composes Badge + Button + Typography + IconButton.
 */
export const CompareBar = React.forwardRef<HTMLDivElement, CompareBarProps>(
  ({ packages, onCompare, error, sx }, ref) => {
    const theme = useTheme();
    const isMobile = useMediaQuery(theme.breakpoints.down('md'));
    const count = packages.length;
    const visible = count > 0;
    const canCompare = count >= 2;

    const statusText = count === 1 ? 'Add another to compare' : 'Ready to compare';

    // Collapse state — mobile only. Starts expanded; when the basket empties
    // we reset so the next fresh fill starts visible.
    const [collapsed, setCollapsed] = React.useState(false);
    const [peeking, setPeeking] = React.useState(false);
    const lastCountRef = React.useRef(count);

    React.useEffect(() => {
      if (!visible) setCollapsed(false);
    }, [visible]);

    // Auto-peek when a package is added while collapsed.
    React.useEffect(() => {
      const prev = lastCountRef.current;
      lastCountRef.current = count;
      if (collapsed && count > prev) {
        setPeeking(true);
        const t = window.setTimeout(() => setPeeking(false), PEEK_DURATION_MS);
        return () => window.clearTimeout(t);
      }
    }, [count, collapsed]);

    /** Effective "is the middle content hidden?" — only on mobile, when the
     *  user has collapsed and we're not currently peeking. */
    const mobileCollapsed = isMobile && collapsed && !peeking;

    return (
      <Slide direction="up" in={visible} mountOnEnter unmountOnExit>
        <Paper
          ref={ref}
          elevation={8}
          role="status"
          aria-live="polite"
          aria-label={`${count} of 3 packages selected for comparison`}
          sx={[
            (t: Theme) => ({
              position: 'fixed',
              // Clear the sticky HelpBar (~40px) + breathing room. FA theme
              // uses a 4px spacing base, so spacing(16) = 64px.
              bottom: t.spacing(16),
              // z-index sits below the mobile map-view drawer (modal: 1300)
              // but above app chrome (appBar: 1100). snackbar (1400) was too
              // aggressive — the drawer visually covers this bar on mobile.
              zIndex: t.zIndex.drawer,
              // Mobile: right-anchored so when the middle collapses the pill
              // appears to retract to the right corner. Desktop: centered.
              ...(isMobile
                ? { right: t.spacing(4), left: 'auto' }
                : { left: 0, right: 0, mx: 'auto' }),
              width: 'fit-content',
              borderRadius: '9999px',
              display: 'flex',
              alignItems: 'center',
              gap: { xs: 1.25, md: 2 },
              px: { xs: 1.5, md: 3 },
              py: { xs: 0.75, md: 1.5 },
              maxWidth: { xs: 'calc(100vw - 32px)', md: 460 },
              overflow: 'hidden',
              transition: `padding ${COLLAPSE_MS}ms ease-out`,
            }),
            ...(Array.isArray(sx) ? sx : [sx]),
          ]}
        >
          {/* Fraction badge — shows "N/3" when expanded, just "N" when
              collapsed on mobile (reads as a circle at mini size). */}
          <Badge
            color="brand"
            variant="soft"
            size={isMobile ? 'medium' : 'large'}
            sx={{
              flexShrink: 0,
              // When collapsed, force the badge toward a circle by
              // equalising min-width and min-height at the medium-badge
              // height (26px).
              ...(mobileCollapsed && {
                minWidth: 'var(--fa-badge-height-md)',
                justifyContent: 'center',
                px: 0,
              }),
            }}
          >
            {mobileCollapsed ? count : `${count}/3`}
          </Badge>

          {/* Middle content (status + Compare CTA) — animates to zero
              max-width when collapsed, letting the pill shrink as one unit
              with the right edge staying fixed. */}
          <Box
            sx={{
              display: 'flex',
              alignItems: 'center',
              gap: { xs: 1.25, md: 2 },
              maxWidth: mobileCollapsed ? 0 : 600,
              opacity: mobileCollapsed ? 0 : 1,
              overflow: 'hidden',
              transition: `max-width ${COLLAPSE_MS}ms ease-out, opacity ${Math.round(
                COLLAPSE_MS * 0.6,
              )}ms ease-out`,
            }}
          >
            <Typography
              variant={isMobile ? 'body2' : 'body1'}
              role={error ? 'alert' : undefined}
              sx={{
                fontWeight: 500,
                whiteSpace: 'nowrap',
                color: error ? 'var(--fa-color-text-brand)' : 'text.primary',
                flexShrink: 0,
              }}
            >
              {error || statusText}
            </Typography>

            <Button
              variant="contained"
              size={isMobile ? 'small' : 'medium'}
              onClick={onCompare}
              disabled={!canCompare}
              tabIndex={mobileCollapsed ? -1 : 0}
              sx={{ flexShrink: 0, borderRadius: '9999px' }}
            >
              Compare
            </Button>
          </Box>

          {/* Mobile-only collapse/expand chevron — grey-filled circle that
              swaps icon direction based on state. Rendered at all times so
              the IconButton container stays in the layout and the icon swap
              happens in place without mount/unmount. */}
          {isMobile && (
            <IconButton
              aria-label={mobileCollapsed ? 'Show comparison basket' : 'Hide comparison basket'}
              aria-expanded={!mobileCollapsed}
              onClick={() => setCollapsed((c) => !c)}
              size="small"
              sx={{
                flexShrink: 0,
                width: 32,
                height: 32,
                borderRadius: '50%',
                bgcolor: 'var(--fa-color-neutral-200)',
                color: 'text.secondary',
                '&:hover': { bgcolor: 'var(--fa-color-neutral-300)' },
              }}
            >
              {mobileCollapsed ? (
                <ChevronLeftRoundedIcon fontSize="small" />
              ) : (
                <ChevronRightRoundedIcon fontSize="small" />
              )}
            </IconButton>
          )}
        </Paper>
      </Slide>
    );
  },
);

CompareBar.displayName = 'CompareBar';
export default CompareBar;
