'use client';

import { LeagueReviewSummary } from '@/components/leagues/LeagueReviewSummary';
import { Button } from '@/ui/Button';
import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { Input } from '@/ui/Input';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
import { useAuth } from '@/components/auth/AuthContext';
import {
  AlertCircle,
  Award,
  Calendar,
  Check,
  CheckCircle2,
  ChevronLeft,
  ChevronRight,
  FileText,
  Loader2,
  Scale,
  Sparkles,
  Trophy,
  Users,
} from 'lucide-react';
import { useRouter } from 'next/navigation';
import { FormEvent, useCallback, useEffect, useState } from 'react';

import { LeagueWizardCommandModel } from '@/lib/command-models/leagues/LeagueWizardCommandModel';

import { useCreateLeagueWizard } from "@/hooks/useLeagueWizardService";
import { useLeagueScoringPresets } from "@/hooks/useLeagueScoringPresets";
import { LeagueBasicsSection } from '@/components/leagues/LeagueBasicsSection';
import { LeagueDropSection } from '@/components/leagues/LeagueDropSection';
import {
  ChampionshipsSection,
  ScoringPatternSection
} from '@/components/leagues/LeagueScoringSection';
import { LeagueStewardingSection } from '@/components/leagues/LeagueStewardingSection';
import { LeagueStructureSection } from '@/components/leagues/LeagueStructureSection';
import { LeagueTimingsSection } from '@/components/leagues/LeagueTimingsSection';
import { LeagueVisibilitySection } from '@/components/leagues/LeagueVisibilitySection';
import type { LeagueConfigFormModel } from '@/lib/types/LeagueConfigFormModel';
import type { LeagueScoringPresetViewModel } from '@/lib/view-models/LeagueScoringPresetViewModel';
import type { Weekday } from '@/lib/types/Weekday';
import type { WizardErrors } from '@/lib/types/WizardErrors';

// ============================================================================
// LOCAL STORAGE PERSISTENCE
// ============================================================================

const STORAGE_KEY = 'gridpilot_league_wizard_draft';
const STORAGE_HIGHEST_STEP_KEY = 'gridpilot_league_wizard_highest_step';

// TODO there is a better place for this
function saveFormToStorage(form: LeagueWizardFormModel): void {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(form));
  } catch {
    // Ignore storage errors (quota exceeded, etc.)
  }
}

// TODO there is a better place for this
function loadFormFromStorage(): LeagueWizardFormModel | null {
  try {
    const stored = localStorage.getItem(STORAGE_KEY);
    if (stored) {
      const parsed = JSON.parse(stored) as LeagueWizardFormModel;
      if (!parsed.seasonName) {
        const seasonStartDate = parsed.timings?.seasonStartDate;
        parsed.seasonName = getDefaultSeasonName(seasonStartDate);
      }
      return parsed;
    }
  } catch {
    // Ignore parse errors
  }
  return null;
}

function clearFormStorage(): void {
  try {
    localStorage.removeItem(STORAGE_KEY);
    localStorage.removeItem(STORAGE_HIGHEST_STEP_KEY);
  } catch {
    // Ignore storage errors
  }
}

function saveHighestStep(step: number): void {
  try {
    const current = getHighestStep();
    if (step > current) {
      localStorage.setItem(STORAGE_HIGHEST_STEP_KEY, String(step));
    }
  } catch {
    // Ignore storage errors
  }
}

function getHighestStep(): number {
  try {
    const stored = localStorage.getItem(STORAGE_HIGHEST_STEP_KEY);
    return stored ? parseInt(stored, 10) : 1;
  } catch {
    return 1;
  }
}

type Step = 1 | 2 | 3 | 4 | 5 | 6 | 7;

type StepName = 'basics' | 'visibility' | 'structure' | 'schedule' | 'scoring' | 'stewarding' | 'review';

type LeagueWizardFormModel = LeagueConfigFormModel & {
  seasonName?: string;
};

interface CreateLeagueWizardProps {
  stepName: StepName;
  onStepChange: (stepName: StepName) => void;
}

function stepNameToStep(stepName: StepName): Step {
  switch (stepName) {
    case 'basics':
      return 1;
    case 'visibility':
      return 2;
    case 'structure':
      return 3;
    case 'schedule':
      return 4;
    case 'scoring':
      return 5;
    case 'stewarding':
      return 6;
    case 'review':
      return 7;
  }
}

function stepToStepName(step: Step): StepName {
  switch (step) {
    case 1:
      return 'basics';
    case 2:
      return 'visibility';
    case 3:
      return 'structure';
    case 4:
      return 'schedule';
    case 5:
      return 'scoring';
    case 6:
      return 'stewarding';
    case 7:
      return 'review';
  }
}

function getDefaultSeasonStartDate(): string {
  // Default to next Saturday
  const now = new Date();
  const daysUntilSaturday = (6 - now.getDay() + 7) % 7 || 7;
  const nextSaturday = new Date(now);
  nextSaturday.setDate(now.getDate() + daysUntilSaturday);
  const [datePart] = nextSaturday.toISOString().split('T');
  return datePart ?? '';
}

function getDefaultSeasonName(seasonStartDate?: string): string {
  if (seasonStartDate) {
    const parsed = new Date(seasonStartDate);
    if (!Number.isNaN(parsed.getTime())) {
      const year = parsed.getFullYear();
      return `Season 1 (${year})`;
    }
  }
  const fallbackYear = new Date().getFullYear();
  return `Season 1 (${fallbackYear})`;
}

function createDefaultForm(): LeagueWizardFormModel {
  const defaultPatternId = 'sprint-main-driver';
  const defaultSeasonStartDate = getDefaultSeasonStartDate();

  return {
    basics: {
      name: '',
      description: '',
      visibility: 'public',
      gameId: 'iracing',
    },
    structure: {
      mode: 'solo',
      maxDrivers: 24,
      multiClassEnabled: false,
    },
    championships: {
      enableDriverChampionship: true,
      enableTeamChampionship: false,
      enableNationsChampionship: false,
      enableTrophyChampionship: false,
    },
    scoring: {
      patternId: defaultPatternId,
      customScoringEnabled: false,
    },
    dropPolicy: {
      strategy: 'bestNResults',
      n: 6,
    },
    timings: {
      practiceMinutes: 20,
      qualifyingMinutes: 30,
      sprintRaceMinutes: 20,
      mainRaceMinutes: 40,
      sessionCount: 2,
      roundsPlanned: 8,
      // Default to Saturday races, weekly, starting next week
      weekdays: ['Sat'] as Weekday[],
      recurrenceStrategy: 'weekly' as const,
      timezoneId: 'UTC',
      seasonStartDate: defaultSeasonStartDate,
    },
    stewarding: {
      decisionMode: 'admin_only',
      requiredVotes: 2,
      requireDefense: false,
      defenseTimeLimit: 48,
      voteTimeLimit: 72,
      protestDeadlineHours: 48,
      stewardingClosesHours: 168,
      notifyAccusedOnProtest: true,
      notifyOnVoteRequired: true,
    },
    seasonName: getDefaultSeasonName(defaultSeasonStartDate),
  };
}

export function CreateLeagueWizard({ stepName, onStepChange }: CreateLeagueWizardProps) {
  const router = useRouter();
  const { session } = useAuth();

  const step = stepNameToStep(stepName);
  const [loading, setLoading] = useState(false);
  const [presetsLoading, setPresetsLoading] = useState(true);
  const [presets, setPresets] = useState<LeagueScoringPresetViewModel[]>([]);
  const [errors, setErrors] = useState<WizardErrors>({});
  const [highestCompletedStep, setHighestCompletedStep] = useState(1);
  const [isHydrated, setIsHydrated] = useState(false);
  
  // Initialize form from localStorage or defaults
  const [form, setForm] = useState<LeagueWizardFormModel>(() =>
    createDefaultForm(),
  );

  // Hydrate from localStorage on mount
  useEffect(() => {
    const stored = loadFormFromStorage();
    if (stored) {
      setForm(stored);
    }
    setHighestCompletedStep(getHighestStep());
    setIsHydrated(true);
  }, []);

  // Save form to localStorage whenever it changes (after hydration)
  useEffect(() => {
    if (isHydrated) {
      saveFormToStorage(form);
    }
  }, [form, isHydrated]);

  // Track highest step reached
  useEffect(() => {
    if (isHydrated) {
      saveHighestStep(step);
      setHighestCompletedStep((prev) => Math.max(prev, step));
    }
  }, [step, isHydrated]);

  // Use the react-query hook for scoring presets
  const { data: queryPresets, error: presetsError } = useLeagueScoringPresets();

  // Sync presets from query to local state
  useEffect(() => {
    if (queryPresets) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      setPresets(queryPresets as any);
      const firstPreset = queryPresets[0];
      if (firstPreset && !form.scoring?.patternId) {
        setForm((prev) => ({
          ...prev,
          scoring: {
            ...prev.scoring,
            patternId: firstPreset.id,
            customScoringEnabled: false,
          },
        }));
      }
      setPresetsLoading(false);
    }
  }, [queryPresets, form.scoring?.patternId]);

  // Handle presets error
  useEffect(() => {
    if (presetsError) {
      setErrors((prev) => ({
        ...prev,
        submit: presetsError instanceof Error ? presetsError.message : 'Failed to load scoring presets',
      }));
    }
  }, [presetsError]);

  // Use the create league mutation
  const createLeagueMutation = useCreateLeagueWizard();

  const validateStep = (currentStep: Step): boolean => {
    // Convert form to LeagueWizardFormData for validation
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const formData: any = {
      leagueId: form.leagueId || '',
      basics: {
        name: form.basics?.name || '',
        description: form.basics?.description || '',
        visibility: (form.basics?.visibility as 'public' | 'private' | 'unlisted') || 'public',
        gameId: form.basics?.gameId || 'iracing',
      },
      structure: {
        mode: (form.structure?.mode as 'solo' | 'fixedTeams') || 'solo',
        maxDrivers: form.structure?.maxDrivers || 0,
        maxTeams: form.structure?.maxTeams || 0,
        driversPerTeam: form.structure?.driversPerTeam || 0,
      },
      championships: {
        enableDriverChampionship: form.championships?.enableDriverChampionship ?? true,
        enableTeamChampionship: form.championships?.enableTeamChampionship ?? false,
        enableNationsChampionship: form.championships?.enableNationsChampionship ?? false,
        enableTrophyChampionship: form.championships?.enableTrophyChampionship ?? false,
      },
      scoring: {
        patternId: form.scoring?.patternId || '',
        customScoringEnabled: form.scoring?.customScoringEnabled ?? false,
      },
      dropPolicy: {
        strategy: (form.dropPolicy?.strategy as 'none' | 'bestNResults' | 'dropWorstN') || 'bestNResults',
        n: form.dropPolicy?.n || 6,
      },
      timings: {
        practiceMinutes: form.timings?.practiceMinutes || 0,
        qualifyingMinutes: form.timings?.qualifyingMinutes || 0,
        sprintRaceMinutes: form.timings?.sprintRaceMinutes || 0,
        mainRaceMinutes: form.timings?.mainRaceMinutes || 0,
        sessionCount: form.timings?.sessionCount || 0,
        roundsPlanned: form.timings?.roundsPlanned || 0,
      },
      stewarding: {
        decisionMode: (form.stewarding?.decisionMode as 'owner_only' | 'admin_vote' | 'steward_panel') || 'admin_only',
        requiredVotes: form.stewarding?.requiredVotes || 0,
        requireDefense: form.stewarding?.requireDefense ?? false,
        defenseTimeLimit: form.stewarding?.defenseTimeLimit || 0,
        voteTimeLimit: form.stewarding?.voteTimeLimit || 0,
        protestDeadlineHours: form.stewarding?.protestDeadlineHours || 0,
        stewardingClosesHours: form.stewarding?.stewardingClosesHours || 0,
        notifyAccusedOnProtest: form.stewarding?.notifyAccusedOnProtest ?? true,
        notifyOnVoteRequired: form.stewarding?.notifyOnVoteRequired ?? true,
      },
    };

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const stepErrors = LeagueWizardCommandModel.validateLeagueWizardStep(formData, currentStep as any);
    setErrors((prev) => ({
      ...prev,
      ...stepErrors,
    }));
    return !LeagueWizardCommandModel.hasWizardErrors(stepErrors);
  };

  const goToNextStep = () => {
    if (!validateStep(step)) {
      return;
    }
    const nextStep = (step < 7 ? ((step + 1) as Step) : step);
    saveHighestStep(nextStep);
    setHighestCompletedStep((prev) => Math.max(prev, nextStep));
    onStepChange(stepToStepName(nextStep));
  };

  const goToPreviousStep = () => {
    const prevStep = (step > 1 ? ((step - 1) as Step) : step);
    onStepChange(stepToStepName(prevStep));
  };

  // Navigate to a specific step (only if it's been reached before)
  const goToStep = useCallback((targetStep: Step) => {
    if (targetStep <= highestCompletedStep) {
      onStepChange(stepToStepName(targetStep));
    }
  }, [highestCompletedStep, onStepChange]);

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault();
    if (loading) return;

    const ownerId = session?.user.userId;
    if (!ownerId) {
      setErrors((prev) => ({
        ...prev,
        submit: 'You must be logged in to create a league',
      }));
      return;
    }

    // Convert form to LeagueWizardFormData for validation
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const formData: any = {
      leagueId: form.leagueId || '',
      basics: {
        name: form.basics?.name || '',
        description: form.basics?.description || '',
        visibility: (form.basics?.visibility as 'public' | 'private' | 'unlisted') || 'public',
        gameId: form.basics?.gameId || 'iracing',
      },
      structure: {
        mode: (form.structure?.mode as 'solo' | 'fixedTeams') || 'solo',
        maxDrivers: form.structure?.maxDrivers || 0,
        maxTeams: form.structure?.maxTeams || 0,
        driversPerTeam: form.structure?.driversPerTeam || 0,
      },
      championships: {
        enableDriverChampionship: form.championships?.enableDriverChampionship ?? true,
        enableTeamChampionship: form.championships?.enableTeamChampionship ?? false,
        enableNationsChampionship: form.championships?.enableNationsChampionship ?? false,
        enableTrophyChampionship: form.championships?.enableTrophyChampionship ?? false,
      },
      scoring: {
        patternId: form.scoring?.patternId || '',
        customScoringEnabled: form.scoring?.customScoringEnabled ?? false,
      },
      dropPolicy: {
        strategy: (form.dropPolicy?.strategy as 'none' | 'bestNResults' | 'dropWorstN') || 'bestNResults',
        n: form.dropPolicy?.n || 6,
      },
      timings: {
        practiceMinutes: form.timings?.practiceMinutes || 0,
        qualifyingMinutes: form.timings?.qualifyingMinutes || 0,
        sprintRaceMinutes: form.timings?.sprintRaceMinutes || 0,
        mainRaceMinutes: form.timings?.mainRaceMinutes || 0,
        sessionCount: form.timings?.sessionCount || 0,
        roundsPlanned: form.timings?.roundsPlanned || 0,
      },
      stewarding: {
        decisionMode: (form.stewarding?.decisionMode as 'owner_only' | 'admin_vote' | 'steward_panel') || 'admin_only',
        requiredVotes: form.stewarding?.requiredVotes || 0,
        requireDefense: form.stewarding?.requireDefense ?? false,
        defenseTimeLimit: form.stewarding?.defenseTimeLimit || 0,
        voteTimeLimit: form.stewarding?.voteTimeLimit || 0,
        protestDeadlineHours: form.stewarding?.protestDeadlineHours || 0,
        stewardingClosesHours: form.stewarding?.stewardingClosesHours || 0,
        notifyAccusedOnProtest: form.stewarding?.notifyAccusedOnProtest ?? true,
        notifyOnVoteRequired: form.stewarding?.notifyOnVoteRequired ?? true,
      },
    };

    const allErrors = LeagueWizardCommandModel.validateAllLeagueWizardSteps(formData);
    setErrors((prev) => ({
      ...prev,
      ...allErrors,
    }));

    if (LeagueWizardCommandModel.hasWizardErrors(allErrors)) {
      onStepChange('basics');
      return;
    }

    setLoading(true);
    setErrors((prev) => {
      const { submit: _, ...rest } = prev;
      return rest;
    });

    try {
      // Use the mutation to create the league
      const result = await createLeagueMutation.mutateAsync({ form, ownerId });
      
      // Clear the draft on successful creation
      clearFormStorage();
      
      // Navigate to the new league
      router.push(`/leagues/${result.leagueId}`);
    } catch (err) {
      const message =
        err instanceof Error ? err.message : 'Failed to create league';
      setErrors((prev) => ({
        ...prev,
        submit: message,
      }));
      setLoading(false);
    }
  };

  // Handler for scoring preset selection (timings default from API)
  const handleScoringPresetChange = (patternId: string) => {
    setForm((prev) => {
      const selectedPreset = presets.find((p) => p.id === patternId);

      return {
        ...prev,
        scoring: {
          ...prev.scoring,
          patternId,
          customScoringEnabled: false,
        },
        timings: selectedPreset
          ? {
              ...prev.timings,
              practiceMinutes: prev.timings?.practiceMinutes ?? selectedPreset.defaultTimings.practiceMinutes,
              qualifyingMinutes: prev.timings?.qualifyingMinutes ?? selectedPreset.defaultTimings.qualifyingMinutes,
              sprintRaceMinutes: prev.timings?.sprintRaceMinutes ?? selectedPreset.defaultTimings.sprintRaceMinutes,
              mainRaceMinutes: prev.timings?.mainRaceMinutes ?? selectedPreset.defaultTimings.mainRaceMinutes,
              sessionCount: selectedPreset.defaultTimings.sessionCount,
            }
          : prev.timings,
      };
    });
  };
  
  const steps = [
    { id: 1 as Step, label: 'Basics', icon: FileText, shortLabel: 'Name' },
    { id: 2 as Step, label: 'Visibility', icon: Award, shortLabel: 'Type' },
    { id: 3 as Step, label: 'Structure', icon: Users, shortLabel: 'Mode' },
    { id: 4 as Step, label: 'Schedule', icon: Calendar, shortLabel: 'Time' },
    { id: 5 as Step, label: 'Scoring', icon: Trophy, shortLabel: 'Points' },
    { id: 6 as Step, label: 'Stewarding', icon: Scale, shortLabel: 'Rules' },
    { id: 7 as Step, label: 'Review', icon: CheckCircle2, shortLabel: 'Done' },
  ];

  const getStepTitle = (currentStep: Step): string => {
    switch (currentStep) {
      case 1:
        return 'Name your league';
      case 2:
        return 'Choose your destiny';
      case 3:
        return 'Choose the structure';
      case 4:
        return 'Set the schedule';
      case 5:
        return 'Scoring & championships';
      case 6:
        return 'Stewarding & protests';
      case 7:
        return 'Review & create';
      default:
        return '';
    }
  };

  const getStepSubtitle = (currentStep: Step): string => {
    switch (currentStep) {
      case 1:
        return 'Give your league a memorable name and tell your story.';
      case 2:
        return 'Will you compete for global rankings or race with friends?';
      case 3:
        return 'Define how races in this season will run.';
      case 4:
        return 'Plan when this season’s races happen.';
      case 5:
        return 'Choose how points and drop scores work for this season.';
      case 6:
        return 'Set how protests and stewarding work for this season.';
      case 7:
        return 'Review your league and first season before launching.';
      default:
        return '';
    }
  };

  const getStepContextLabel = (currentStep: Step): string => {
    if (currentStep === 1 || currentStep === 2) {
      return 'League setup';
    }
    if (currentStep >= 3 && currentStep <= 6) {
      return 'Season setup';
    }
    return 'League & Season summary';
  };

  const currentStepData = steps.find((s) => s.id === step);
  const CurrentStepIcon = currentStepData?.icon ?? FileText;

  return (
    <Box as="form" onSubmit={handleSubmit} maxWidth="4xl" mx="auto" pb={8}>
      {/* Header with icon */}
      <Box mb={8}>
        <Stack direction="row" align="center" gap={3} mb={3}>
          <Box display="flex" h="11" w="11" alignItems="center" justifyContent="center" rounded="xl" bg="bg-primary-blue/20" border borderColor="border-primary-blue/20">
            <Icon icon={Sparkles} size={5} color="text-primary-blue" />
          </Box>
          <Box>
            <Heading level={1} fontSize={{ base: '2xl', sm: '3xl' }}>
              Create a new league
            </Heading>
            <Text size="sm" color="text-gray-500" block>
              We'll also set up your first season in {steps.length} easy steps.
            </Text>
            <Text size="xs" color="text-gray-500" block mt={1}>
              A league is your long-term brand. Each season is a block of races you can run again and again.
            </Text>
          </Box>
        </Stack>
      </Box>

      {/* Desktop Progress Bar */}
      <Box display={{ base: 'none', md: 'block' }} mb={8}>
        <Box position="relative">
          {/* Background track */}
          <Box position="absolute" top="5" left="6" right="6" h="0.5" bg="bg-charcoal-outline" rounded="full" />
          {/* Progress fill */}
          <Box
            position="absolute"
            top="5"
            left="6"
            h="0.5"
            bg="bg-gradient-to-r from-primary-blue to-neon-aqua"
            rounded="full"
            transition
            width={`calc(${((step - 1) / (steps.length - 1)) * 100}% - 48px)`}
          />

          <Box position="relative" display="flex" justifyContent="between">
            {steps.map((wizardStep) => {
              const isCompleted = wizardStep.id < step;
              const isCurrent = wizardStep.id === step;
              const isAccessible = wizardStep.id <= highestCompletedStep;
              const StepIcon = wizardStep.icon;

              return (
                <Box
                  as="button"
                  key={wizardStep.id}
                  type="button"
                  onClick={() => goToStep(wizardStep.id)}
                  disabled={!isAccessible}
                  display="flex"
                  flexDirection="col"
                  alignItems="center"
                  bg="bg-transparent"
                  borderStyle="none"
                  cursor={isAccessible ? 'pointer' : 'not-allowed'}
                  opacity={!isAccessible ? 0.6 : 1}
                >
                  <Box
                    position="relative"
                    zIndex={10}
                    display="flex"
                    h="10"
                    w="10"
                    alignItems="center"
                    justifyContent="center"
                    rounded="full"
                    transition
                    bg={isCurrent || isCompleted ? 'bg-primary-blue' : 'bg-iron-gray'}
                    color={isCurrent || isCompleted ? 'text-white' : 'text-gray-400'}
                    border={!isCurrent && !isCompleted}
                    borderColor="border-charcoal-outline"
                    shadow={isCurrent ? '0_0_24px_rgba(25,140,255,0.5)' : undefined}
                    transform={isCurrent ? 'scale-110' : isCompleted ? 'hover:scale-105' : undefined}
                  >
                    {isCompleted ? (
                      <Icon icon={Check} size={4} strokeWidth={3} />
                    ) : (
                      <Icon icon={StepIcon} size={4} />
                    )}
                  </Box>
                  <Box mt={2} textAlign="center">
                    <Text
                      size="xs"
                      weight="medium"
                      transition
                      color={isCurrent ? 'text-white' : isCompleted ? 'text-primary-blue' : isAccessible ? 'text-gray-400' : 'text-gray-500'}
                    >
                      {wizardStep.label}
                    </Text>
                  </Box>
                </Box>
              );
            })}
          </Box>
        </Box>
      </Box>

      {/* Mobile Progress */}
      <Box display={{ base: 'block', md: 'none' }} mb={6}>
        <Box display="flex" alignItems="center" justifyContent="between" mb={2}>
          <Stack direction="row" align="center" gap={2}>
            <Icon icon={CurrentStepIcon} size={4} color="text-primary-blue" />
            <Text size="sm" weight="medium" color="text-white">{currentStepData?.label}</Text>
          </Stack>
          <Text size="xs" color="text-gray-500">
            {step}/{steps.length}
          </Text>
        </Box>
        <Box h="1.5" bg="bg-charcoal-outline" rounded="full" overflow="hidden">
          <Box
            h="full"
            bg="bg-gradient-to-r from-primary-blue to-neon-aqua"
            rounded="full"
            transition
            height="full"
            width={`${(step / steps.length) * 100}%`}
          />
        </Box>
        {/* Step dots */}
        <Box display="flex" justifyContent="between" mt={2} px={0.5}>
          {steps.map((s) => (
            <Box
              key={s.id}
              h="1.5"
              rounded="full"
              transition
              width={s.id === step ? '4' : '1.5'}
              bg={s.id === step ? 'bg-primary-blue' : s.id < step ? 'bg-primary-blue/60' : 'bg-charcoal-outline'}
            />
          ))}
        </Box>
      </Box>

      {/* Main Card */}
      <Card position="relative" overflow="hidden">
        {/* Top gradient accent */}
        <Box position="absolute" top="0" left="0" right="0" h="1" bg="bg-gradient-to-r from-transparent via-primary-blue to-transparent" />

        {/* Step header */}
        <Box display="flex" alignItems="start" gap={4} mb={6}>
          <Box display="flex" h="12" w="12" alignItems="center" justifyContent="center" rounded="xl" bg="bg-primary-blue/10" flexShrink={0} transition>
            <Icon icon={CurrentStepIcon} size={6} color="text-primary-blue" />
          </Box>
          <Box flexGrow={1} minWidth="0">
            <Heading level={2} fontSize={{ base: 'xl', md: '2xl' }} color="text-white">
              <Stack direction="row" align="center" gap={2} flexWrap="wrap">
                <Text>{getStepTitle(step)}</Text>
                <Text size="xs" weight="medium" px={2} py={0.5} rounded="full" border borderColor="border-charcoal-outline" bg="bg-iron-gray/60" color="text-gray-300">
                  {getStepContextLabel(step)}
                </Text>
              </Stack>
            </Heading>
            <Text size="sm" color="text-gray-400" block mt={1}>
              {getStepSubtitle(step)}
            </Text>
          </Box>
          <Box display={{ base: 'none', sm: 'flex' }} alignItems="center" gap={1.5} px={3} py={1.5} rounded="full" bg="bg-deep-graphite" border borderColor="border-charcoal-outline">
            <Text size="xs" color="text-gray-500">Step</Text>
            <Text size="sm" weight="semibold" color="text-white">{step}</Text>
            <Text size="xs" color="text-gray-500">/ {steps.length}</Text>
          </Box>
        </Box>

        {/* Divider */}
        <Box h="px" bg="bg-gradient-to-r from-transparent via-charcoal-outline to-transparent" mb={6} />

        {/* Step content with min-height for consistency */}
        <Box minHeight="320px">
         {step === 1 && (
           <Box animate="fade-in" gap={8} display="flex" flexDirection="col">
             <LeagueBasicsSection
               form={form}
               onChange={setForm}
               errors={errors.basics ?? {}}
             />
             <Box rounded="xl" border borderColor="border-charcoal-outline" bg="bg-iron-gray/40" p={4}>
               <Box display="flex" alignItems="center" justifyContent="between" gap={2} mb={2}>
                 <Box>
                   <Text size="xs" weight="semibold" color="text-gray-300" uppercase letterSpacing="wide">
                     First season
                   </Text>
                   <Text size="xs" color="text-gray-500" block>
                     Name the first season that will run in this league.
                   </Text>
                 </Box>
               </Box>
               <Box mt={2} display="flex" flexDirection="col" gap={2}>
                 <Text as="label" size="sm" weight="medium" color="text-gray-300" block>
                   Season name
                 </Text>
                 <Input
                   value={form.seasonName ?? ''}
                   onChange={(e) =>
                     setForm((prev) => ({
                       ...prev,
                       seasonName: e.target.value,
                     }))
                   }
                   placeholder="e.g., Season 1 (2025)"
                 />
                 <Text size="xs" color="text-gray-500" block>
                   Seasons are the individual competitive runs inside your league. You can run Season 2, Season 3, or parallel seasons later.
                 </Text>
               </Box>
             </Box>
           </Box>
         )}

          {step === 2 && (
            <Box animate="fade-in">
              <LeagueVisibilitySection
                form={form}
                onChange={setForm}
                errors={
                  errors.basics?.visibility
                    ? { visibility: errors.basics.visibility }
                    : {}
                }
              />
            </Box>
          )}

          {step === 3 && (
            <Box animate="fade-in" display="flex" flexDirection="col" gap={4}>
              <Box mb={2}>
                <Text size="xs" color="text-gray-500" block>
                  Applies to: First season of this league.
                </Text>
                <Text size="xs" color="text-gray-500" block>
                  These settings only affect this season. Future seasons can use different formats.
                </Text>
              </Box>
              <LeagueStructureSection
                form={form}
                onChange={setForm}
                readOnly={false}
              />
            </Box>
          )}

          {step === 4 && (
            <Box animate="fade-in" display="flex" flexDirection="col" gap={4}>
              <Box mb={2}>
                <Text size="xs" color="text-gray-500" block>
                  Applies to: First season of this league.
                </Text>
                <Text size="xs" color="text-gray-500" block>
                  These settings only affect this season. Future seasons can use different formats.
                </Text>
              </Box>
              <LeagueTimingsSection
                form={form}
                onChange={setForm}
                errors={errors.timings ?? {}}
              />
            </Box>
          )}

          {step === 5 && (
            <Box animate="fade-in" display="flex" flexDirection="col" gap={8}>
              <Box mb={2}>
                <Text size="xs" color="text-gray-500" block>
                  Applies to: First season of this league.
                </Text>
                <Text size="xs" color="text-gray-500" block>
                  These settings only affect this season. Future seasons can use different formats.
                </Text>
              </Box>
              {/* Scoring Pattern Selection */}
              <ScoringPatternSection
                scoring={form.scoring || {}}
                presets={presets}
                readOnly={presetsLoading}
                patternError={errors.scoring?.patternId ?? ''}
                onChangePatternId={handleScoringPresetChange}
                onToggleCustomScoring={() =>
                  setForm((prev) => ({
                    ...prev,
                    scoring: {
                      ...prev.scoring,
                      customScoringEnabled: !(prev.scoring?.customScoringEnabled),
                    },
                  }))
                }
              />

              {/* Divider */}
              <Box h="px" bg="bg-gradient-to-r from-transparent via-charcoal-outline to-transparent" />
              
              {/* Championships & Drop Rules side by side on larger screens */}
              <Box display="grid" gridCols={{ base: 1, lg: 2 }} gap={6}>
                <ChampionshipsSection form={form} onChange={setForm} readOnly={presetsLoading} />
                <LeagueDropSection form={form} onChange={setForm} readOnly={false} />
              </Box>

              {errors.submit && (
                <Box display="flex" alignItems="start" gap={3} rounded="lg" bg="bg-warning-amber/10" p={4} border borderColor="border-warning-amber/20">
                  <Icon icon={AlertCircle} size={5} color="text-warning-amber" flexShrink={0} mt={0.5} />
                  <Text size="sm" color="text-warning-amber">{errors.submit}</Text>
                </Box>
              )}
            </Box>
          )}

          {step === 6 && (
            <Box animate="fade-in" display="flex" flexDirection="col" gap={4}>
              <Box mb={2}>
                <Text size="xs" color="text-gray-500" block>
                  Applies to: First season of this league.
                </Text>
                <Text size="xs" color="text-gray-500" block>
                  These settings only affect this season. Future seasons can use different formats.
                </Text>
              </Box>
              <LeagueStewardingSection
                form={form}
                onChange={setForm}
                readOnly={false}
              />
            </Box>
          )}

          {step === 7 && (
            <Box animate="fade-in" display="flex" flexDirection="col" gap={6}>
              <LeagueReviewSummary form={form} presets={presets} />
              {errors.submit && (
                <Box display="flex" alignItems="start" gap={3} rounded="lg" bg="bg-warning-amber/10" p={4} border borderColor="border-warning-amber/20">
                  <Icon icon={AlertCircle} size={5} color="text-warning-amber" flexShrink={0} mt={0.5} />
                  <Text size="sm" color="text-warning-amber">{errors.submit}</Text>
                </Box>
              )}
            </Box>
          )}
        </Box>
      </Card>

      {/* Navigation */}
      <Box display="flex" alignItems="center" justifyContent="between" mt={6}>
        <Button
          type="button"
          variant="secondary"
          disabled={step === 1 || loading}
          onClick={goToPreviousStep}
          icon={<Icon icon={ChevronLeft} size={4} />}
        >
          <Text display={{ base: 'none', md: 'inline-block' }}>Back</Text>
        </Button>

        <Box display="flex" alignItems="center" gap={3}>
          {/* Mobile step dots */}
          <Box display={{ base: 'flex', sm: 'none' }} alignItems="center" gap={1}>
            {steps.map((s) => (
              <Box
                key={s.id}
                h="1.5"
                rounded="full"
                transition
                width={s.id === step ? '3' : '1.5'}
                bg={s.id === step ? 'bg-primary-blue' : s.id < step ? 'bg-primary-blue/50' : 'bg-charcoal-outline'}
              />
            ))}
          </Box>

          {step < 7 ? (
            <Button
              type="button"
              variant="primary"
              disabled={loading}
              onClick={goToNextStep}
              icon={<Icon icon={ChevronRight} size={4} />}
              flexDirection="row-reverse"
            >
              <Text>Continue</Text>
            </Button>
          ) : (
            <Button
              type="submit"
              variant="primary"
              disabled={loading}
              minWidth="150px"
              justifyContent="center"
              icon={loading ? <Icon icon={Loader2} size={4} animate="spin" /> : <Icon icon={Sparkles} size={4} />}
            >
              {loading ? (
                <Text>Creating…</Text>
              ) : (
                <Text>Create League</Text>
              )}
            </Button>
          )}
        </Box>
      </Box>

      {/* Helper text */}
      <Text size="xs" color="text-gray-500" align="center" block mt={4}>
        This will create your league and its first season. You can edit both later.
      </Text>
    </Box>
  );
}
