import React from 'react';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import ButtonBase from '@mui/material/ButtonBase';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import StarRoundedIcon from '@mui/icons-material/StarRounded';
import VerifiedOutlinedIcon from '@mui/icons-material/VerifiedOutlined';
import type { SxProps, Theme } from '@mui/material/styles';
import { IconButton } from '../../atoms/IconButton';
import { Typography } from '../../atoms/Typography';
import { ProviderCard } from '../ProviderCard';
import type { ProviderData } from '../../pages/ProvidersStep';
import type { ProviderMapActiveState } from '../../organisms/ProviderMap';

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

/** Props for the FA MapProviderDrawer molecule */
export interface MapProviderDrawerProps {
  /** Current active state from `ProviderMap` (wire via `onActiveChange`).
   *  `null` = no active pin/cluster; drawer is hidden. */
  active: ProviderMapActiveState | null;
  /** Fires when the close X is tapped. Typically wired to the map's
   *  imperative `clearActive()`. */
  onClose: () => void;
  /** Fires when the single-provider card is tapped (entire card clickable).
   *  Typically navigates to that provider's packages. */
  onSelectProvider: (id: string) => void;
  /** Fires when a cluster row is tapped. Typically wired to the map's
   *  imperative `drillIntoProvider()` which pans + zooms + swaps the
   *  drawer's content to a single-provider card. */
  onDrillIntoProvider: (id: string) => void;
  /** MUI sx prop for the root Paper — merged onto the default positioning. */
  sx?: SxProps<Theme>;
}

// ─── Cluster row ────────────────────────────────────────────────────────────

const ClusterRow: React.FC<{
  provider: ProviderData;
  onClick: () => void;
}> = ({ provider: p, onClick }) => (
  <ButtonBase
    onClick={onClick}
    sx={{
      width: '100%',
      justifyContent: 'flex-start',
      textAlign: 'left',
      px: 2,
      py: 1.25,
      gap: 1,
      // Start-align so the verified icon sits on the name's baseline —
      // matches the desktop ClusterPopup row treatment.
      alignItems: 'flex-start',
      borderBottom: '1px solid',
      borderColor: 'divider',
      '&:last-of-type': { borderBottom: 'none' },
      '&:hover': { bgcolor: 'var(--fa-color-surface-subtle)' },
    }}
  >
    {/* Verified-icon slot — reserved width + fixed line-height so the icon
        sits on the name's line-box regardless of location/rating meta
        below. Mirrors desktop ClusterPopup's treatment (D043 refinement). */}
    <Box
      sx={{
        width: 18,
        height: '1.25em',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        flexShrink: 0,
      }}
    >
      {p.verified && <VerifiedOutlinedIcon sx={{ fontSize: 16, color: 'primary.main' }} />}
    </Box>

    <Box sx={{ flex: 1, minWidth: 0 }}>
      <Typography
        variant="body2"
        sx={{
          fontWeight: 600,
          color: p.verified ? 'primary.main' : 'text.primary',
          lineHeight: 1.25,
          mb: 0.25,
        }}
      >
        {p.name}
      </Typography>
      <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, color: 'text.secondary' }}>
        <Typography variant="caption">{p.location}</Typography>
        {p.rating != null && (
          <Box sx={{ display: 'inline-flex', alignItems: 'center', gap: 0.25 }}>
            <StarRoundedIcon sx={{ fontSize: 14, color: 'warning.main' }} />
            <Typography variant="caption">{p.rating.toFixed(1)}</Typography>
          </Box>
        )}
      </Box>
    </Box>

    {p.startingPrice != null && (
      <Box sx={{ flexShrink: 0, textAlign: 'right', pl: 1 }}>
        <Typography variant="caption" sx={{ display: 'block', color: 'text.secondary' }}>
          From
        </Typography>
        <Typography
          variant="body2"
          sx={{ fontWeight: 600, color: p.verified ? 'primary.main' : 'text.primary' }}
        >
          ${p.startingPrice.toLocaleString('en-AU')}
        </Typography>
      </Box>
    )}
  </ButtonBase>
);

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

/**
 * Bottom drawer that surfaces `ProviderMap`'s popup content outside the
 * map itself. Used by the mobile map-first layout (see D045): the map
 * runs full-bleed, and when a pin or cluster is tapped the drawer slides
 * up from the bottom with the appropriate content.
 *
 * **Two content states, driven by `active`:**
 * - `active.provider` → renders a `ProviderCard` edge-to-edge, entire card
 *   clickable (fires `onSelectProvider`)
 * - `active.cluster` → renders a verified-first list of rows (verified icon
 *   slot + name + location + rating + "From $X"); tapping a row fires
 *   `onDrillIntoProvider` which is wired to the map's imperative
 *   `drillIntoProvider()` (pans + zooms, then swaps `active` to that
 *   provider — the drawer content flips to the single-provider card).
 *
 * **Animation:** slides up via `transform: translateY()` + 220ms transition.
 * When `active.exiting` is true, the drawer slides down immediately (the
 * map organism is in the middle of its 180ms exit fade on the hidden pin
 * beneath). `visibility: hidden` kicks in only after the slide completes,
 * so the drawer stays in the DOM for the exit animation.
 *
 * **Positioning:** uses `position: absolute; bottom: 0; left: 0; right: 0`
 * by default — the consumer MUST render this inside a relatively-positioned
 * container (typically the map-view `<main>`). Override via `sx` if needed.
 *
 * Related: row layout mirrors `ClusterPopup` (the anchored on-map variant);
 * future consolidation possible if both container contracts converge.
 */
export const MapProviderDrawer = React.forwardRef<HTMLDivElement, MapProviderDrawerProps>(
  ({ active, onClose, onSelectProvider, onDrillIntoProvider, sx }, ref) => {
    const provider = active?.provider ?? null;
    const cluster = active?.cluster ?? null;
    const isOpen = !!(active && !active.exiting && (provider || cluster));
    const isExiting = !!active?.exiting;

    const ariaLabel = provider
      ? `${provider.name} details`
      : cluster
        ? `${cluster.providers.length} providers in this area`
        : undefined;

    return (
      <Paper
        ref={ref}
        elevation={0}
        role="dialog"
        aria-label={ariaLabel}
        aria-hidden={!isOpen}
        sx={[
          {
            position: 'absolute',
            bottom: 0,
            left: 0,
            right: 0,
            zIndex: 3,
            maxHeight: '60vh',
            overflow: 'auto',
            borderRadius: 0,
            borderTopLeftRadius: 16,
            borderTopRightRadius: 16,
            boxShadow: 'var(--fa-shadow-lg)',
            transform: isOpen ? 'translateY(0)' : 'translateY(100%)',
            transition: 'transform 220ms ease-out',
            pointerEvents: isOpen ? 'auto' : 'none',
            visibility: isOpen || isExiting ? 'visible' : 'hidden',
          },
          ...(Array.isArray(sx) ? sx : [sx]),
        ]}
      >
        {/* Header strip — holds the close X (and the cluster count when
            applicable) so neither sits over the card image below.
            Horizontal padding matches the cluster rows (px: 2) so the
            heading aligns with the row content beneath. */}
        <Box
          sx={{
            display: 'flex',
            alignItems: 'center',
            minHeight: 40,
            px: 2,
            py: 0.5,
            gap: 1,
          }}
        >
          {cluster && !provider && (
            <Typography variant="labelLg" sx={{ color: 'text.secondary', display: 'block' }}>
              {cluster.providers.length} providers in this area
            </Typography>
          )}
          <IconButton
            aria-label="Close"
            onClick={onClose}
            size="small"
            sx={{
              ml: 'auto',
              width: 32,
              height: 32,
              color: 'text.secondary',
              '&:hover': { bgcolor: 'var(--fa-color-surface-subtle)' },
            }}
          >
            <CloseRoundedIcon sx={{ fontSize: 20 }} />
          </IconButton>
        </Box>

        {/* Single-provider content — entire card clickable. Card runs
            edge-to-edge with all corners squared; the drawer Paper provides
            the top radius. */}
        {provider && (
          <ProviderCard
            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}. Tap to view packages.`}
            sx={{ borderRadius: 0, boxShadow: 'none', border: 'none' }}
          />
        )}

        {/* Cluster list content — tap a row to drill in */}
        {cluster && !provider && (
          <Box sx={{ pb: 1 }}>
            {[...cluster.providers]
              .sort((a, b) => Number(!!b.verified) - Number(!!a.verified))
              .map((p) => (
                <ClusterRow key={p.id} provider={p} onClick={() => onDrillIntoProvider(p.id)} />
              ))}
          </Box>
        )}
      </Paper>
    );
  },
);

MapProviderDrawer.displayName = 'MapProviderDrawer';
export default MapProviderDrawer;
