import React, { useEffect } from 'react';
import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery';
import VerifiedOutlinedIcon from '@mui/icons-material/VerifiedOutlined';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import type { SxProps, Theme } from '@mui/material/styles';
import { WizardLayout } from '../../templates/WizardLayout';
import { ProviderCardCompact } from '../../molecules/ProviderCardCompact';
import { ServiceOption } from '../../molecules/ServiceOption';
import { NearbyPackageCard } from '../../molecules/NearbyPackageCard';
import { PackageDetail } from '../../organisms/PackageDetail';
import { Typography } from '../../atoms/Typography';
import { Divider } from '../../atoms/Divider';
import { Link } from '../../atoms/Link';
import type { PackageData, PackagesStepProvider, ProviderTier, SecondaryList } from './types';

export type {
  PackageData,
  PackagesStepProvider,
  NearbyVerifiedPackage,
  ProviderTier,
  SecondaryList,
} from './types';

// ─── Tier copy map ───────────────────────────────────────────────────────────

interface TierCopy {
  heading: string;
  subheading: (isPrePlanning: boolean) => string;
  arrangeLabel: string;
  priceDisclaimer?: string;
  itemizedUnavailable: boolean;
  emptyDetailMessage: string;
}

const TIER_COPY: Record<ProviderTier, TierCopy> = {
  verified: {
    heading: 'Choose a funeral package',
    subheading: (isPrePlanning) =>
      isPrePlanning
        ? 'Compare packages to find what suits your wishes. Nothing is committed until you confirm.'
        : 'Each package includes a set of services. You can customise your selections in the next steps.',
    arrangeLabel: 'Make Arrangement',
    itemizedUnavailable: false,
    emptyDetailMessage: "Select a package to see what's included.",
  },
  tier3: {
    heading: 'Explore available packages',
    subheading: (isPrePlanning) =>
      isPrePlanning
        ? 'Browse estimated packages to get a sense of what this provider offers. Nothing is committed.'
        : 'These packages are based on publicly available information. Make an enquiry to confirm details and pricing.',
    arrangeLabel: 'Make an enquiry',
    priceDisclaimer:
      "Prices are estimates based on publicly available information and may not reflect the provider's current pricing.",
    itemizedUnavailable: false,
    emptyDetailMessage: "Select a package to see what's included.",
  },
  tier2: {
    heading: 'Explore available packages',
    subheading: (isPrePlanning) =>
      isPrePlanning
        ? 'Browse estimated packages to get a sense of what this provider offers. Nothing is committed.'
        : 'These packages are based on publicly available information. Make an enquiry to confirm details and pricing.',
    arrangeLabel: 'Make an enquiry',
    priceDisclaimer:
      "Prices are estimates based on publicly available information and may not reflect the provider's current pricing.",
    itemizedUnavailable: true,
    emptyDetailMessage: 'Select a package to see more details.',
  },
};

// Show at most this many "other packages from this provider" inline before
// switching to "top N + See all →" behaviour.
const SAME_PROVIDER_INLINE_LIMIT = 3;

// ─── Props ───────────────────────────────────────────────────────────────────

export interface PackagesStepProps {
  /** Provider shown at the top of the list panel */
  provider: PackagesStepProvider;
  /** Provider tier — drives copy, CTA label, disclaimer, itemised-unavailable state */
  providerTier: ProviderTier;
  /** Packages in the primary list (filtered by user preferences, or all when `showAllFromProvider`) */
  packages: PackageData[];
  /** Secondary list below the primary one — same-provider-more or nearby-verified. Suppressed when `showAllFromProvider` is true. */
  secondaryList?: SecondaryList;
  /** Currently selected package ID */
  selectedPackageId: string | null;
  /** Callback when a primary-list package is selected (or cleared via mobile back) */
  onSelectPackage: (id: string | null) => void;
  /** Callback when "Make Arrangement" / "Make an enquiry" is clicked */
  onArrange: () => void;
  /** Callback when the "Compare" button on the PackageDetail panel is clicked */
  onCompare?: () => void;
  /** Callback when a nearby-verified package card is clicked (route change to that provider) */
  onNearbyPackageClick?: (id: string) => void;
  /**
   * Callback when "See all N packages from [Provider]" is clicked.
   * Expected to route to the same PackagesStep with `showAllFromProvider` set.
   * Only used when secondaryList.kind === 'same-provider-more' and list length > 3.
   */
  onSeeAllPackages?: () => void;
  /** Callback when the provider card is clicked (future: opens provider profile) */
  onProviderClick?: () => void;
  /** Callback for the Back button */
  onBack: () => void;
  /**
   * When true, renders the "All packages from [Provider]" variant:
   * flat list, no grouping, no secondary list, no "Matching your preferences" heading.
   * Caller passes the full package list in `packages`.
   */
  showAllFromProvider?: boolean;
  /** Validation error */
  error?: string;
  /** Whether the arrange action is loading */
  loading?: boolean;
  /** Navigation bar */
  navigation?: React.ReactNode;
  /** Whether this is a pre-planning flow */
  isPrePlanning?: boolean;
  /** MUI sx prop */
  sx?: SxProps<Theme>;
}

// ─── Helpers ─────────────────────────────────────────────────────────────────

/** Accent bar + label — used for both "Matching your preferences" and "Other packages from [X]". */
function GroupHeading({
  label,
  emphasis = 'primary',
}: {
  label: string;
  emphasis?: 'primary' | 'secondary';
}) {
  return (
    <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, mb: 2 }}>
      <Box
        sx={{
          width: 3,
          height: 20,
          borderRadius: 1,
          bgcolor: emphasis === 'primary' ? 'primary.main' : 'text.secondary',
          flexShrink: 0,
        }}
      />
      <Typography
        variant="body2"
        sx={{
          fontWeight: 600,
          color: emphasis === 'primary' ? 'text.primary' : 'text.secondary',
        }}
      >
        {label}
      </Typography>
    </Box>
  );
}

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

/**
 * Package selection step — tier-aware, unified page component.
 *
 * Handles all three provider tiers (verified, tier3, tier2) via the
 * `providerTier` prop. Header copy, CTA label, price disclaimer, and
 * itemised-unavailable state are derived from tier.
 *
 * Left column layout varies by `secondaryList`:
 * - `same-provider-more` (verified): primary "Matching your preferences"
 *   list + "Other packages from [Provider]" list. If >3 other packages,
 *   shows top 3 + "See all N packages from [Provider] →" link that routes
 *   to the same page with `showAllFromProvider`.
 * - `nearby-verified` (unverified tiers): primary list + "Similar packages
 *   from verified providers nearby" list (NearbyPackageCard).
 *
 * When `showAllFromProvider` is true, renders a flat "All packages from
 * [Provider]" list with no grouping and no secondary list. The caller
 * preserves `selectedPackageId` across this navigation.
 *
 * Pure presentation component — props in, callbacks out.
 *
 * Spec: documentation/steps/steps/03_packages.yaml
 */
export const PackagesStep: React.FC<PackagesStepProps> = ({
  provider,
  providerTier,
  packages,
  secondaryList,
  selectedPackageId,
  onSelectPackage,
  onArrange,
  onCompare,
  onNearbyPackageClick,
  onSeeAllPackages,
  onProviderClick,
  onBack,
  showAllFromProvider = false,
  error,
  loading = false,
  navigation,
  isPrePlanning = false,
  sx,
}) => {
  const copy = TIER_COPY[providerTier];
  const selectedPackage = packages.find((p) => p.id === selectedPackageId);

  // Mobile drill-in: when a package is selected on mobile, swap the list view
  // for the detail view. Back button clears selection to return to the list.
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('md'));
  const mobileShowDetail = isMobile && selectedPackageId != null;

  useEffect(() => {
    if (mobileShowDetail) window.scrollTo({ top: 0, behavior: 'auto' });
  }, [mobileShowDetail]);

  const handleLayoutBack = mobileShowDetail ? () => onSelectPackage(null) : onBack;
  const layoutBackLabel = mobileShowDetail ? 'Back to packages' : 'Back';

  // Secondary list suppressed in "show all" mode.
  const activeSecondaryList = showAllFromProvider ? undefined : secondaryList;
  const hasSecondary = Boolean(activeSecondaryList);

  // For same-provider-more, show top N inline; surface "See all" when over limit.
  const sameProviderPackages =
    activeSecondaryList?.kind === 'same-provider-more' ? activeSecondaryList.packages : [];
  const sameProviderOverflow = sameProviderPackages.length > SAME_PROVIDER_INLINE_LIMIT;
  const sameProviderVisible = sameProviderOverflow
    ? sameProviderPackages.slice(0, SAME_PROVIDER_INLINE_LIMIT)
    : sameProviderPackages;

  const heading = showAllFromProvider ? `All packages from ${provider.name}` : copy.heading;
  const subheading = showAllFromProvider
    ? `Every package ${provider.name} offers, including those outside your preferences.`
    : copy.subheading(isPrePlanning);

  const primaryListAriaLabel = showAllFromProvider
    ? `All packages from ${provider.name}`
    : 'Funeral packages';

  return (
    <WizardLayout
      variant="list-detail"
      navigation={navigation}
      showBackLink
      backLabel={layoutBackLabel}
      onBack={handleLayoutBack}
      sx={sx}
      secondaryPanel={
        <Box
          sx={{
            display: {
              xs: mobileShowDetail ? 'block' : 'none',
              md: 'block',
            },
          }}
        >
          {selectedPackage ? (
            <PackageDetail
              name={selectedPackage.name}
              price={selectedPackage.price}
              sections={selectedPackage.sections}
              total={selectedPackage.total}
              extras={selectedPackage.extras}
              terms={selectedPackage.terms}
              onArrange={onArrange}
              onCompare={onCompare}
              arrangeDisabled={loading}
              arrangeLabel={copy.arrangeLabel}
              priceDisclaimer={copy.priceDisclaimer}
              itemizedUnavailable={copy.itemizedUnavailable}
            />
          ) : (
            <Box
              sx={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                height: '100%',
                minHeight: 300,
                bgcolor: 'var(--fa-color-brand-50)',
                borderRadius: 2,
                p: 4,
              }}
            >
              <Typography variant="body1" color="text.secondary" sx={{ textAlign: 'center' }}>
                {copy.emptyDetailMessage}
              </Typography>
            </Box>
          )}
        </Box>
      }
    >
      {/* List column — hidden on mobile when a package is selected (drill-in) */}
      <Box
        sx={{
          display: {
            xs: mobileShowDetail ? 'none' : 'block',
            md: 'block',
          },
        }}
      >
        {/* Provider compact card */}
        <Box sx={{ mb: 6 }}>
          <ProviderCardCompact
            name={provider.name}
            location={provider.location}
            imageUrl={provider.imageUrl}
            rating={provider.rating}
            reviewCount={provider.reviewCount}
            onClick={onProviderClick}
          />
        </Box>

        {/* Heading + subheading */}
        <Typography variant="h4" component="h1" sx={{ mb: 0.5 }} tabIndex={-1}>
          {heading}
        </Typography>
        <Typography variant="body2" color="text.secondary" sx={{ mb: 6 }}>
          {subheading}
        </Typography>

        {/* Error */}
        {error && (
          <Typography
            variant="body2"
            sx={{ mb: 2, color: 'var(--fa-color-text-brand)' }}
            role="alert"
          >
            {error}
          </Typography>
        )}

        {/* ─── Primary packages ─── */}
        {/* Show "Matching your preferences" heading only when a secondary list follows */}
        {hasSecondary && !showAllFromProvider && <GroupHeading label="Matching your preferences" />}

        <Box
          role="radiogroup"
          aria-label={primaryListAriaLabel}
          sx={{ display: 'flex', flexDirection: 'column', gap: 2, mb: 4 }}
        >
          {packages.map((pkg) => (
            <ServiceOption
              key={pkg.id}
              name={pkg.name}
              description={pkg.description}
              price={pkg.price}
              selected={selectedPackageId === pkg.id}
              onClick={() => onSelectPackage(pkg.id)}
            />
          ))}

          {packages.length === 0 && (
            <Box sx={{ py: 4, textAlign: 'center' }}>
              <Typography variant="body2" color="text.secondary">
                No packages match your current preferences.
              </Typography>
            </Box>
          )}
        </Box>

        {/* ─── Secondary: same-provider-more ─── */}
        {activeSecondaryList?.kind === 'same-provider-more' && sameProviderPackages.length > 0 && (
          <>
            <Divider sx={{ my: 8 }} />
            <GroupHeading label={`Other packages from ${provider.name}`} emphasis="secondary" />
            <Box
              role="radiogroup"
              aria-label={`Other packages from ${provider.name}`}
              sx={{
                display: 'flex',
                flexDirection: 'column',
                gap: 2,
                mb: sameProviderOverflow ? 2 : 3,
                opacity: 0.85,
              }}
            >
              {sameProviderVisible.map((pkg) => (
                <ServiceOption
                  key={pkg.id}
                  name={pkg.name}
                  description={pkg.description}
                  price={pkg.price}
                  selected={selectedPackageId === pkg.id}
                  onClick={() => onSelectPackage(pkg.id)}
                />
              ))}
            </Box>

            {sameProviderOverflow && onSeeAllPackages && (
              <Box sx={{ mb: 3 }}>
                <Link
                  component="button"
                  type="button"
                  onClick={onSeeAllPackages}
                  underline="hover"
                  sx={{
                    display: 'inline-flex',
                    alignItems: 'center',
                    gap: 0.5,
                    fontWeight: 600,
                  }}
                >
                  See {sameProviderPackages.length - SAME_PROVIDER_INLINE_LIMIT} more packages from
                  this provider
                  <ArrowForwardIcon sx={{ fontSize: 16 }} aria-hidden />
                </Link>
              </Box>
            )}
          </>
        )}

        {/* ─── Secondary: nearby-verified ─── */}
        {activeSecondaryList?.kind === 'nearby-verified' &&
          activeSecondaryList.packages.length > 0 && (
            <>
              <Divider sx={{ my: 8 }} />
              <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
                <VerifiedOutlinedIcon sx={{ fontSize: 16, color: 'primary.main' }} aria-hidden />
                <Typography variant="body2" sx={{ fontWeight: 600, color: 'text.primary' }}>
                  Similar packages from verified providers nearby
                </Typography>
              </Box>
              <Box
                aria-label="Similar packages from nearby verified providers"
                sx={{ display: 'flex', flexDirection: 'column', gap: 2, mb: 3 }}
              >
                {activeSecondaryList.packages.map((pkg) => (
                  <NearbyPackageCard
                    key={pkg.id}
                    packageName={pkg.packageName}
                    price={pkg.price}
                    providerName={pkg.providerName}
                    location={pkg.location}
                    rating={pkg.rating}
                    reviewCount={pkg.reviewCount}
                    onClick={onNearbyPackageClick ? () => onNearbyPackageClick(pkg.id) : undefined}
                  />
                ))}
              </Box>
            </>
          )}
      </Box>
    </WizardLayout>
  );
};

PackagesStep.displayName = 'PackagesStep';
export default PackagesStep;
