import { useState, useEffect, useCallback, useMemo } from 'react'
import { toast } from 'sonner'
import { Barbell, TrendUp, BookOpen, MapPin, User as UserIcon } from '@phosphor-icons/react'

import type { Workout, WorkoutSession, WorkoutHistory } from '@/types/workout'
import type {
  Exercise,
  ExerciseMedia,
  CustomExerciseMedia,
  ExerciseNote,
  PersonalModification
} from '@/types/exercise'
import type { PersonalRecord } from '@/types/progress'
import type { Gym as GymType } from '@/types/gym'
import type { UserData, WorkoutGoal, Achievement } from '@/types/user'
import { AppNotification } from '@/types/notifications'
import type { TrainerStudent } from '@/services/trainerService'

import { useAuth } from '@/hooks/useAuth'
import { AuthScreen } from '@/components/AuthScreen'

import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Button } from '@/components/ui/button'
import { Progress as ProgressBar } from '@/components/ui/progress'

import { AppLanguageAutoDetectionNotifier } from '@/components/AppLanguageAutoDetectionNotifier'
import { AppEmailVerificationBanner } from '@/components/AppEmailVerificationBanner'
import { AppInfoDialog } from '@/components/AppInfoDialog'
import { AppNotificationPanel } from '@/components/AppNotificationPanel'
import { UserAdminPanel } from '@/components/UserAdminPanel'
import { TrainerPanel } from '@/components/TrainerPanel'
import { AppPWAInstallPrompt } from '@/components/AppPWAInstallPrompt'
import { AppUpdateAvailableDialog } from '@/components/AppUpdateAvailableDialog'
import { ExerciseCatalogUpdateIndicator } from '@/components/ExerciseCatalogUpdateIndicator'
import { AppUserWelcome } from '@/components/AppUserWelcome'
import { WorkoutGoalsDialog } from '@/components/WorkoutGoalsDialog'
import { WorkoutGoalDeleteDialog } from '@/components/WorkoutGoalDeleteDialog'
import { UserAchievementsDialog } from '@/components/UserAchievementsDialog'
import { WorkoutCancelDialog } from '@/components/WorkoutCancelDialog'
import { GymDeleteDialog } from '@/components/GymDeleteDialog'
import { ExercisesNoteDeleteDialog } from '@/components/ExercisesNoteDeleteDialog'
import { ExercisesPersonalModificationDeleteDialog } from '@/components/ExercisesPersonalModificationDeleteDialog'
import { WorkoutSummaryDialog } from '@/components/WorkoutSummaryDialog'
import { WorkoutHistoryDialog } from '@/components/WorkoutHistoryDialog'
import { WorkoutActiveExercise } from '@/components/WorkoutActiveExercise'
import { ExercisesDetailDialog } from '@/components/ExercisesDetailDialog'
import { ExercisesCustomMediaDialog } from '@/components/ExercisesCustomMediaDialog'
import { ExercisesNotesDialog } from '@/components/ExercisesNotesDialog'
import { ExercisesPersonalModificationsDialog } from '@/components/ExercisesPersonalModificationsDialog'
import { PremiumFeaturePaywall, type PremiumFeature } from '@/components/PremiumFeaturePaywall'
import { GymBuilder } from '@/components/GymBuilder'
import { Gym } from '@/components/Gym'
import { Workouts } from '@/components/Workouts'
import { Exercises } from '@/components/Exercises'
import { Progress as ProgressTab } from '@/components/Progress'
import { User } from '@/components/User'

import AppLogoImage from '@/assets/images/AppLogoImage-29x29.png'
import { BRANDING } from '@/config/branding'

import { useExerciseTranslation } from '@/lib/exercise-translations'
import { logTranslationReport } from '@/lib/translation-verification'

import { exerciseDatabase, isBuiltInExercise } from '@/data/exercises'
import { exerciseDataManager } from '@/data/exercises/ExerciseDataManager'

import { useSortPreferences } from '@/hooks/useSortPreferences'
import { useProgressPreferences } from '@/hooks/useProgressPreferences'
import { useNotificationSystem } from '@/hooks/useNotificationSystem'
import { useNotificationScheduler } from '@/hooks/useNotificationScheduler'
import { useGymDistances } from '@/hooks/useGymDistances'
import { usePWAFeatures } from '@/hooks/usePWAFeatures'
import { useDatabase } from '@/contexts/DatabaseContext'
import { generateDatabaseId, type DatabaseIdOptions } from '@/lib/database-id'
import { useWorkoutSync } from '@/hooks/useWorkoutSync'
import { useGoalSync } from '@/hooks/useGoalSync'
import { usePersonalRecordSync } from '@/hooks/usePersonalRecordSync'
import { useGymSync } from '@/hooks/useGymSync'
import { useAchievementSync } from '@/hooks/useAchievementSync'
import { useRealtimeSync } from '@/hooks/useRealtimeSync'
import { useSyncQueue } from '@/hooks/useSyncQueue'
import { useFavoritesSync, useNotesSync, useModificationsSync, useMediaSync } from '@/hooks/useExerciseSync'
import { useGoalProgressCalculator } from '@/hooks/useGoalProgressCalculator'

import { I18nProvider, useTranslation } from '@/i18n'
import { useNotificationTriggers } from './hooks/useNotificationTriggers'
import { AdBanner } from '@/components/ads/AdBanner'

function AppContent() {
  const { isAuthenticated, isGuest, isLoading: authLoading, user, logout } = useAuth()
  const { t, language } = useTranslation()
  const { translateExercise } = useExerciseTranslation()
  const { 
    preferences: sortPreferences, 
    updateExerciseSort, 
    updateWorkoutSort, 
    toggleExerciseSortReverse, 
    toggleWorkoutSortReverse 
  } = useSortPreferences()
  
  const {
    preferences: progressPreferences,
    updatePeriod: updateProgressPeriod
  } = useProgressPreferences()
  
  // Database hook for unified data management
  const { dataAccessors, dataSetters, dataHelpers, isInitialized: isDbInitialized } = useDatabase()

  const generateId = useCallback((options?: DatabaseIdOptions) => {
    return dataHelpers.generateId?.(options) ?? generateDatabaseId(options)
  }, [dataHelpers])
  
  // Check if user needs to see welcome screen first
  const userWelcomeCompleted = dataAccessors.userWelcomeCompleted
  const userData = dataAccessors.userData

  // Delay welcome screen by 10 seconds for better UX
  const [welcomeDelayPassed, setWelcomeDelayPassed] = useState(false)
  useEffect(() => {
    if (userWelcomeCompleted === false) {
      const timer = setTimeout(() => {
        setWelcomeDelayPassed(true)
      }, 10000) // 10 seconds delay
      return () => clearTimeout(timer)
    }
  }, [userWelcomeCompleted])

  // Notification System
  const {
    getUnreadCount,
    getVisibleNotifications,
    markAsRead,
    markAsUnread,
    toggleReadStatus,
    archiveNotification,
    deleteNotification,
    markAllAsRead,
    clearAllNotifications,
    isInitialized,
    notifications,
    createNotification,
    getNotificationSettings,
  } = useNotificationSystem()
  const {
    checkWorkoutReminders,
    checkGoalDeadlines,
    checkWorkoutStreaks,
    createAchievementNotification,
  } = useNotificationTriggers({
    isInitialized,
    notifications,
    createNotification,
    getNotificationSettings,
  })
  
  // Automatic Notification Scheduler - handles time-based workout reminders
  useNotificationScheduler()

  // Check exercise catalog manifest on app start (detects updates and triggers background download)
  useEffect(() => {
    exerciseDataManager.getManifest(language).catch(console.warn)
  }, [language])

  useEffect(() => {
    if (process.env.NODE_ENV === 'development') {
      // Log translation report for current language after a short delay
      setTimeout(() => {
        console.info('🌍 GymTracker: Exercise translation verification')
        logTranslationReport(language)
      }, 1000)
    }
  }, [language])
  
  // Destructure data for convenience
  const {
    workouts,
    workoutHistory,
    activeSession,
    personalRecords,
    favoriteExercises,
    customExerciseMedia,
    exerciseNotes,
    personalModifications,
    workoutGoals,
    achievements,
    gyms
  } = dataAccessors

  // Sync queue for offline operations
  const { addToQueue, processQueue } = useSyncQueue()

  // Workout sync with API (for authenticated users)
  const { saveWorkoutToApi, deleteWorkoutFromApi, saveWorkoutHistoryToApi } = useWorkoutSync({
    workouts: workouts || [],
    setWorkouts: dataSetters.setWorkouts,
    addToSyncQueue: addToQueue,
  })

  // Goal sync with API (for authenticated users)
  const { saveGoalToApi, deleteGoalFromApi } = useGoalSync({
    workoutGoals: workoutGoals || [],
    setWorkoutGoals: dataSetters.setWorkoutGoals,
    addToSyncQueue: addToQueue,
  })

  // Personal record sync with API (for authenticated users)
  const { savePersonalRecordsToApi } = usePersonalRecordSync({
    personalRecords: personalRecords || [],
    setPersonalRecords: dataSetters.setPersonalRecords,
    addToSyncQueue: addToQueue,
  })

  // Gym sync with API (for authenticated users)
  const { saveGymToApi, deleteGymFromApi } = useGymSync({
    gyms: gyms || [],
    setGyms: dataSetters.setGyms,
    isInitialized: isDbInitialized,
    addToSyncQueue: addToQueue,
  })

  // Achievement sync with API (for authenticated users)
  const { saveAchievementToApi } = useAchievementSync({
    achievements: achievements || [],
    setAchievements: dataSetters.setAchievements,
    isInitialized: isDbInitialized,
    addToSyncQueue: addToQueue,
  })

  // Exercise favorites sync with API (for authenticated users)
  const { addFavoriteToApi, removeFavoriteFromApi } = useFavoritesSync({
    favorites: favoriteExercises || [],
    setFavorites: dataSetters.setFavoriteExercises,
    isInitialized: isDbInitialized,
    addToSyncQueue: addToQueue,
  })

  // Exercise notes sync with API (for authenticated users)
  const { saveNoteToApi, deleteNoteFromApi } = useNotesSync({
    notes: exerciseNotes || [],
    setNotes: dataSetters.setExerciseNotes,
    isInitialized: isDbInitialized,
    addToSyncQueue: addToQueue,
  })

  // Personal modifications sync with API (for authenticated users)
  const { saveModificationToApi, deleteModificationFromApi } = useModificationsSync({
    modifications: personalModifications || [],
    setModifications: dataSetters.setPersonalModifications,
    isInitialized: isDbInitialized,
    addToSyncQueue: addToQueue,
  })

  // Custom exercise media sync with API (for authenticated users)
  const { saveMediaToApi, deleteMediaFromApi, uploadAndSyncMedia } = useMediaSync({
    customMedia: customExerciseMedia || {},
    setCustomMedia: dataSetters.setCustomExerciseMedia,
    isInitialized: isDbInitialized,
    addToSyncQueue: addToQueue,
  })

  // Real-time sync via WebSocket (for authenticated users)
  // This handles trainer:workout-assigned, trainer:note-sent, notification:new, sync:update events
  useRealtimeSync({
    workouts: workouts || [],
    setWorkouts: dataSetters.setWorkouts,
    createNotification,
    processQueue,
  })
  
  // Gym distances
  const { distances: gymDistances, isLoading: isLoadingDistances } = useGymDistances(gyms || [])
  
  // PWA Features
  const {
    pwaSettings,
    isPWAInstalled,
    isPWAInstallable,
    showAchievementNotification,
    showPersonalRecordNotification,
  } = usePWAFeatures()

  // Goal progress calculator for updating goals after workout completion
  const updateGoalSilently = useCallback((goal: WorkoutGoal) => {
    dataHelpers.updateWorkoutGoal(goal)
    saveGoalToApi(goal)
  }, [dataHelpers, saveGoalToApi])

  const createAchievementSilently = useCallback((achievement: Achievement) => {
    dataHelpers.addAchievement(achievement)
    saveAchievementToApi(achievement)
    createAchievementNotification(achievement)
    
    if (pwaSettings.achievements) {
      showAchievementNotification(achievement.title, achievement.description || '')
    }
  }, [dataHelpers, saveAchievementToApi, createAchievementNotification, pwaSettings.achievements, showAchievementNotification])

  const { calculateGoalProgress } = useGoalProgressCalculator({
    onUpdateGoal: updateGoalSilently,
    onCreateAchievement: createAchievementSilently,
  })

  // Update goals after workout completion
  const updateGoalsAfterWorkout = useCallback((newWorkoutHistory: WorkoutHistory[]) => {
    if (workoutGoals && workoutGoals.length > 0) {
      calculateGoalProgress(workoutGoals, newWorkoutHistory)
    }
  }, [workoutGoals, calculateGoalProgress])
  
  const [activeTab, setActiveTab] = useState('workouts')
  
  // Persist selected student in sessionStorage so it survives page refresh
  const [activeTrainerStudent, setActiveTrainerStudent] = useState<TrainerStudent | null>(() => {
    try {
      const stored = sessionStorage.getItem('activeTrainerStudent')
      return stored ? JSON.parse(stored) : null
    } catch {
      return null
    }
  })
  
  const [showPWAInstallPrompt, setShowPWAInstallPrompt] = useState(false)
  const handleClosePWAInstallPrompt = useCallback(() => {
    setShowPWAInstallPrompt(false)
  }, [setShowPWAInstallPrompt])

  // Trainer student mode handlers
  const handleSelectTrainerStudent = useCallback((student: TrainerStudent) => {
    setActiveTrainerStudent(student)
    sessionStorage.setItem('activeTrainerStudent', JSON.stringify(student))
  }, [])

  const handleExitStudentMode = useCallback(() => {
    setActiveTrainerStudent(null)
    sessionStorage.removeItem('activeTrainerStudent')
  }, [])

  const handleNavigateToTab = useCallback((tab: 'workouts' | 'progress') => {
    setActiveTab(tab)
  }, [])
  
  // Active workout session states
  const [currentExerciseIndex, setCurrentExerciseIndex] = useState(0)
  const [showWorkoutSummary, setShowWorkoutSummary] = useState(false)
  const [completedWorkout, setCompletedWorkout] = useState<WorkoutHistory | null>(null)
  const [workoutWasCompleted, setWorkoutWasCompleted] = useState(false)
  const [showCancelWorkoutDialog, setShowCancelWorkoutDialog] = useState(false)
  const [cancelWorkoutName, setCancelWorkoutName] = useState('')
  
  // Exercise detail states (used across components)
  const [selectedExercise, setSelectedExercise] = useState<Exercise | null>(null)
  const [showExerciseDetail, setShowExerciseDetail] = useState(false)
  const [showCustomMediaDialog, setShowCustomMediaDialog] = useState(false)
  const [showExerciseNotesDialog, setShowExerciseNotesDialog] = useState(false)
  const [showPersonalModificationsDialog, setShowPersonalModificationsDialog] = useState(false)
  
  // Premium paywall state
  const [showPremiumPaywall, setShowPremiumPaywall] = useState(false)
  const [premiumPaywallFeature, setPremiumPaywallFeature] = useState<PremiumFeature>('customMedia')
  
  // Gym management states (used by Gym component)
  const [showGymBuilder, setShowGymBuilder] = useState(false)
  const [gymBuilderInitialTemplate, setGymBuilderInitialTemplate] = useState<string | undefined>()
  const [editingGym, setEditingGym] = useState<GymType | undefined>()
  const [showDeleteGymDialog, setShowDeleteGymDialog] = useState(false)
  const [gymToDelete, setGymToDelete] = useState<GymType | null>(null)
  const [showDeleteNoteDialog, setShowDeleteNoteDialog] = useState(false)
  const [noteToDelete, setNoteToDelete] = useState<ExerciseNote | null>(null)
  const [showDeleteModificationDialog, setShowDeleteModificationDialog] = useState(false)
  const [modificationToDelete, setModificationToDelete] = useState<PersonalModification | null>(null)
  const [showWorkoutGoalsDialog, setShowWorkoutGoalsDialog] = useState(false)
  const [showWorkoutGoalDeleteDialog, setShowWorkoutGoalDeleteDialog] = useState(false)
  const [goalToDelete, setGoalToDelete] = useState<WorkoutGoal | null>(null)
  const [showUserAchievementsDialog, setShowUserAchievementsDialog] = useState(false)
  const [showWorkoutHistoryDialog, setShowWorkoutHistoryDialog] = useState(false)
  const [showAppInfoDialog, setShowAppInfoDialog] = useState(false)
  const exerciseDisplayMode = dataAccessors.exerciseDisplayMode || 'card'
  const setExerciseDisplayMode = dataSetters.setExerciseDisplayMode

  // AdMob handlers - @capgo/capacitor-admob uses native overlay, no space reservation needed
  const handleAdFailedToLoad = () => {
    console.error('AdMob: Banner failed to load')
  }

  const logoSrc = BRANDING.appLogoUrl || AppLogoImage

  // Check for notifications based on data changes
  useEffect(() => {
    if (workoutHistory && workoutHistory.length >= 0) {
      checkWorkoutReminders(workoutHistory)
      checkWorkoutStreaks(workoutHistory)
    }
  }, [workoutHistory, checkWorkoutReminders, checkWorkoutStreaks])

  useEffect(() => {
    if (workoutGoals && workoutGoals.length > 0) {
      checkGoalDeadlines(workoutGoals)
    }
  }, [workoutGoals, checkGoalDeadlines])

  // PWA Install prompt handling
  useEffect(() => {
    if (isPWAInstallable && !isPWAInstalled && !showPWAInstallPrompt) {
      // Show install prompt after a delay
      const timer = setTimeout(() => {
        setShowPWAInstallPrompt(true)
      }, 5000)
      
      return () => clearTimeout(timer)
    }
  }, [isPWAInstallable, isPWAInstalled, showPWAInstallPrompt])

  // Handle PWA shortcuts
  useEffect(() => {
    const handlePWAAction = (event: CustomEvent<{ type: string; tab?: string }>) => {
      const { type, tab } = event.detail
      
      switch (type) {
        case 'quick-workout':
          setActiveTab('workouts')
          break
        case 'navigate-tab':
          if (tab) {
            setActiveTab(tab)
          }
          break
      }
    }

    window.addEventListener('pwa-action', handlePWAAction)
    
    return () => {
      window.removeEventListener('pwa-action', handlePWAAction)
    }
  }, [])

  // Handle notification actions
  const handleNotificationAction = (notification: AppNotification) => {
    switch (notification.actionType) {
      case 'start-workout':
        setActiveTab('workouts')
        break
      case 'view-goal':
        setShowWorkoutGoalsDialog(true)
        break
      case 'view-achievement':
        setShowUserAchievementsDialog(true)
        break
      default:
        break
    }
  }

  // User welcome handlers
  const handleUserWelcomeComplete = (newUserData: Partial<UserData>) => {
    const now = new Date().toISOString()
    const profile: UserData = {
      ...newUserData,
  id: newUserData.id || generateId({ prefix: 'user' }),
      createdAt: newUserData.createdAt || now,
      updatedAt: now,
    } as UserData
    
    dataSetters.setUserData(profile)
    dataSetters.setUserWelcomeCompleted(true)
    toast.success(t('notifications.profileSaved'))
  }

  const handleUserWelcomeSkip = () => {
    dataSetters.setUserWelcomeCompleted(true)
  }

  const handleSaveWorkout = (workout: Workout) => {
    dataHelpers.updateWorkout(workout)
    saveWorkoutToApi(workout) // Sync with API
    toast.success(t('notifications.workoutSaved'))
  }

  const handleDeleteWorkout = (workoutId: string) => {
    dataHelpers.deleteWorkout(workoutId)
    deleteWorkoutFromApi(workoutId) // Sync with API
    toast.success(t('notifications.workoutDeleted'))
  }

  const handleStartWorkout = (workout: Workout) => {
    const session: WorkoutSession = {
      id: generateId({ prefix: 'session' }),
      workoutId: workout.id,
      workout: {
        ...workout,
        exercises: (workout.exercises || []).map(ex => {
          // Enhance exercise with complete data from database and custom media
          const fullExercise = exerciseDatabase.find(dbEx => dbEx.id === ex.exerciseId)
          const enhancedExercise = fullExercise ? enhanceExerciseWithCustomMedia(fullExercise) : ex.exercise
          
          return {
            ...ex,
            exercise: enhancedExercise,
            sets: (ex.sets || []).map(set => ({ ...set, completed: false }))
          }
        })
      },
      startTime: new Date().toISOString(),
      completedExercises: [],
      currentExerciseIndex: 0,
      currentSetIndex: 0
    }
    dataSetters.setActiveSession(session)
    setCurrentExerciseIndex(0)
    toast.success(t('notifications.workoutStarted'))
  }

  const handleSetComplete = (setIndex: number, reps: number, weight: number) => {
    if (!activeSession) return

    dataSetters.setActiveSession(current => {
      if (!current) return null
      
      const updated = { ...current }
      const workoutExercise = (updated.workout.exercises || [])[currentExerciseIndex]
      if (!workoutExercise || !workoutExercise.sets || !workoutExercise.sets[setIndex]) return current

      workoutExercise.sets[setIndex] = {
        reps,
        weight,
        completed: true
      }
      
      return updated
    })
    
    toast.success(t('notifications.setCompleted'))
  }

  const handleNextExercise = () => {
    if (!activeSession) return

    if (currentExerciseIndex < (activeSession.workout.exercises || []).length - 1) {
      setCurrentExerciseIndex(currentExerciseIndex + 1)
    } else {
      // Workout complete
      const activeGym = dataHelpers.getActiveGym()
      const completedWorkout: WorkoutHistory = {
        id: generateId({ prefix: 'workout_history' }),
        workoutId: activeSession.workoutId,
        workoutName: activeSession.workout.name,
        completedAt: new Date().toISOString(),
        duration: Math.floor((Date.now() - new Date(activeSession.startTime).getTime()) / 1000 / 60),
        totalSets: (activeSession.workout.exercises || []).reduce((sum, ex) => sum + (ex.sets || []).length, 0),
        totalReps: (activeSession.workout.exercises || []).reduce((sum, ex) => 
          sum + (ex.sets || []).reduce((setSum, set) => setSum + (set.completed ? set.reps : 0), 0), 0),
        totalWeight: (activeSession.workout.exercises || []).reduce((sum, ex) => 
          sum + (ex.sets || []).reduce((setSum, set) => setSum + (set.completed ? set.weight * set.reps : 0), 0), 0),
        gymId: activeGym?.id || null,
        exercises: (activeSession.workout.exercises || []).map(ex => ({
          exerciseId: ex.exerciseId,
          exerciseName: ex.exercise?.name ?? ex.name ?? ex.exerciseId,
          sets: ex.sets.filter(set => set.completed),
          selectedVariation: ex.selectedVariation
        }))
      }
      
      // Check for personal records
      checkAndUpdatePersonalRecords(completedWorkout)
      
      dataHelpers.addWorkoutHistory(completedWorkout)
      
      // Update goal progress with new workout
      const updatedHistory = [...(workoutHistory || []), completedWorkout]
      updateGoalsAfterWorkout(updatedHistory)
      
      // Sync to API (non-blocking)
      saveWorkoutHistoryToApi(completedWorkout)
      
      dataSetters.setActiveSession(null)
      setCurrentExerciseIndex(0)
      
      // Show workout summary
      setCompletedWorkout(completedWorkout)
      setWorkoutWasCompleted(true)
      setShowWorkoutSummary(true)
      
      toast.success(t('notifications.workoutCompleted'))
    }
  }

  const handlePrevExercise = () => {
    if (!activeSession) return
    if (currentExerciseIndex > 0) {
      setCurrentExerciseIndex(currentExerciseIndex - 1)
    }
  }

  const handleStopWorkout = () => {
    if (!activeSession) return

    // Check if any sets have been completed
    const totalCompletedSets = (activeSession.workout.exercises || []).reduce((sum, ex) => 
      sum + (ex.sets || []).filter(set => set.completed).length, 0)

    // If no sets completed, show confirmation dialog
    if (totalCompletedSets === 0) {
      setCancelWorkoutName(activeSession.workout.name)
      setShowCancelWorkoutDialog(true)
      return
    }

    // If sets were completed, proceed with normal stop logic
    proceedWithStopWorkout()
  }

  const proceedWithStopWorkout = () => {
    if (!activeSession) return

    // Create a partial workout history for stopped workout
    const activeGym = dataHelpers.getActiveGym()
    const stoppedWorkout: WorkoutHistory = {
      id: generateId({ prefix: 'workout_history' }),
      workoutId: activeSession.workoutId,
      workoutName: activeSession.workout.name,
      completedAt: new Date().toISOString(),
      duration: Math.floor((Date.now() - new Date(activeSession.startTime).getTime()) / 1000 / 60),
      totalSets: (activeSession.workout.exercises || []).reduce((sum, ex) => 
        sum + (ex.sets || []).filter(set => set.completed).length, 0),
      totalReps: (activeSession.workout.exercises || []).reduce((sum, ex) => 
        sum + (ex.sets || []).reduce((setSum, set) => setSum + (set.completed ? set.reps : 0), 0), 0),
      totalWeight: (activeSession.workout.exercises || []).reduce((sum, ex) => 
        sum + (ex.sets || []).reduce((setSum, set) => setSum + (set.completed ? set.weight * set.reps : 0), 0), 0),
      gymId: activeGym?.id || null,
      exercises: (activeSession.workout.exercises || [])
        .filter(ex => (ex.sets || []).some(set => set.completed))
        .map(ex => ({
          exerciseId: ex.exerciseId,
          exerciseName: ex.exercise?.name ?? ex.name ?? ex.exerciseId,
          sets: ex.sets.filter(set => set.completed),
          selectedVariation: ex.selectedVariation
        }))
    }

    // Only save to history if there were completed sets
    if (stoppedWorkout.totalSets > 0) {
      // Check for personal records on completed exercises
      checkAndUpdatePersonalRecords(stoppedWorkout)
      dataHelpers.addWorkoutHistory(stoppedWorkout)
      
      // Update goal progress with new workout
      const updatedHistory = [...(workoutHistory || []), stoppedWorkout]
      updateGoalsAfterWorkout(updatedHistory)
      
      // Sync to API (non-blocking)
      saveWorkoutHistoryToApi(stoppedWorkout)
    }

    dataSetters.setActiveSession(null)
    setCurrentExerciseIndex(0)
    
    // Show workout summary if there was any progress
    if (stoppedWorkout.totalSets > 0) {
      setCompletedWorkout(stoppedWorkout)
      setWorkoutWasCompleted(false)
      setShowWorkoutSummary(true)
    }
    
    toast.info(t('notifications.workoutStopped'))
  }

  const handleCancelWorkoutConfirm = () => {
    setShowCancelWorkoutDialog(false)
    dataSetters.setActiveSession(null)
    setCurrentExerciseIndex(0)
    toast.info(t('notifications.workoutStopped'))
  }

  const handleCancelWorkoutCancel = () => {
    setShowCancelWorkoutDialog(false)
  }

  const hasNonEmptyString = (value?: string | null) => typeof value === 'string' && value.trim().length > 0
  const hasNonEmptyStringArray = (value?: string[] | null) => Array.isArray(value) && value.length > 0
  const exerciseMediaHasSources = (media?: ExerciseMedia | null) =>
    !!(media && (hasNonEmptyString(media.video) || hasNonEmptyString(media.image) || hasNonEmptyStringArray(media.thumbnails) || hasNonEmptyString(media.gif)))
  const mergeExerciseMedia = (base?: ExerciseMedia, override?: ExerciseMedia): ExerciseMedia | undefined => {
    const merged: ExerciseMedia = {
      ...(base ?? {}),
      ...(override ?? {})
    }

    return exerciseMediaHasSources(merged) ? merged : undefined
  }

  const handleViewExerciseDetails = (exercise: Exercise) => {
    // Only proceed if we have a valid exercise with required data
    if (!exercise || !exercise.id || !exercise.name) {
      console.warn('handleViewExerciseDetails called with invalid exercise:', exercise)
      return
    }
    
    // If the exercise is missing some fields, try to find it in the database
    let completeExercise = exercise
    if (
      !hasNonEmptyStringArray(exercise.instructions) ||
      !hasNonEmptyStringArray(exercise.tips) ||
      !hasNonEmptyStringArray(exercise.commonMistakes) ||
      !exercise.difficulty
    ) {
      console.log('Exercise missing some data, attempting to complete from database:', {
        id: exercise.id,
        missingFields: {
          instructions: !hasNonEmptyStringArray(exercise.instructions),
          tips: !hasNonEmptyStringArray(exercise.tips),
          commonMistakes: !hasNonEmptyStringArray(exercise.commonMistakes),
          difficulty: !exercise.difficulty
        }
      })
      
      const foundExercise = exerciseDatabase.find(ex => ex.id === exercise.id)
      if (foundExercise) {
        console.log('Found complete exercise in database, merging data')
        // Merge the found exercise with any custom data from the passed exercise
        completeExercise = {
          ...foundExercise,
          ...exercise,
          // Ensure we don't override essential complete data with undefined/null values
          instructions: hasNonEmptyStringArray(exercise.instructions) ? exercise.instructions : foundExercise.instructions,
          tips: hasNonEmptyStringArray(exercise.tips) ? exercise.tips : foundExercise.tips,
          commonMistakes: hasNonEmptyStringArray(exercise.commonMistakes) ? exercise.commonMistakes : foundExercise.commonMistakes,
          difficulty: exercise.difficulty || foundExercise.difficulty,
          media: mergeExerciseMedia(foundExercise.media, exercise.media)
        }
      } else {
        console.warn('Could not find exercise in database:', exercise.id)
      }
    }
    
    const enhancedExercise = enhanceExerciseWithCustomMedia(completeExercise)
    setSelectedExercise(enhancedExercise)
    setShowExerciseDetail(true)

    const shouldHydrate =
      !hasNonEmptyString(completeExercise.description) ||
      !hasNonEmptyStringArray(completeExercise.instructions) ||
      !hasNonEmptyStringArray(completeExercise.tips) ||
      !hasNonEmptyStringArray(completeExercise.commonMistakes) ||
      !exerciseMediaHasSources(completeExercise.media)

    if (shouldHydrate) {
      const targetExerciseId = completeExercise.id
      // Hydrate stale exercise records with the translated JSON source when essential fields are missing
      ;(async () => {
        try {
          const fetchedExercise = await exerciseDataManager.getExercise(language, targetExerciseId)
          if (!fetchedExercise) {
            return
          }
          
          const hydratedExercise: Exercise = {
            ...fetchedExercise,
            ...completeExercise,
            description: hasNonEmptyString(completeExercise.description) ? completeExercise.description : fetchedExercise.description,
            instructions: hasNonEmptyStringArray(completeExercise.instructions) ? completeExercise.instructions : fetchedExercise.instructions,
            tips: hasNonEmptyStringArray(completeExercise.tips) ? completeExercise.tips : fetchedExercise.tips,
            commonMistakes: hasNonEmptyStringArray(completeExercise.commonMistakes) ? completeExercise.commonMistakes : fetchedExercise.commonMistakes,
            difficulty: completeExercise.difficulty || fetchedExercise.difficulty,
            media: mergeExerciseMedia(fetchedExercise.media, completeExercise.media),
            setsConfigs: completeExercise.setsConfigs ?? fetchedExercise.setsConfigs,
            variations: completeExercise.variations ?? fetchedExercise.variations,
            muscles: completeExercise.muscles?.length ? completeExercise.muscles : fetchedExercise.muscles,
          }

          const hydratedEnhanced = enhanceExerciseWithCustomMedia(hydratedExercise)
          setSelectedExercise(prev => (prev && prev.id === targetExerciseId ? hydratedEnhanced : prev))
        } catch (error) {
          console.error('Failed to hydrate exercise data for detail dialog:', error)
        }
      })()
    }
  }

  const handleCloseExerciseDetail = () => {
    setShowExerciseDetail(false)
    setSelectedExercise(null)
  }

  const handleCustomMediaClick = (exercise: Exercise) => {
    setSelectedExercise(exercise)
    setShowCustomMediaDialog(true)
  }

  // Handler for guests trying to access premium features
  const handleGuestPremiumFeatureClick = (feature: PremiumFeature, exercise?: Exercise) => {
    if (exercise) {
      setSelectedExercise(exercise)
    }
    setPremiumPaywallFeature(feature)
    setShowPremiumPaywall(true)
  }

  const handleClosePremiumPaywall = () => {
    setShowPremiumPaywall(false)
  }
  const handlePaywallSignIn = async () => {
    setShowPremiumPaywall(false)
    // Exit guest mode and show login screen
    await logout()
  }
  const handlePaywallSignUp = async () => {
    setShowPremiumPaywall(false)
    // Set preferred mode to register before exiting guest mode
    localStorage.setItem('auth_preferred_mode', 'register')
    await logout()
  }

  const handleCloseCustomMediaDialog = () => {
    setShowCustomMediaDialog(false)
    // Don't clear selectedExercise here - let ExerciseDetailDialog handle it
  }

  const handleSaveCustomMedia = (exerciseId: string, media: CustomExerciseMedia | null) => {
    dataHelpers.saveCustomExerciseMedia(exerciseId, media)
    
    // Sync with API
    if (media) {
      saveMediaToApi(exerciseId, media)
    } else {
      deleteMediaFromApi(exerciseId)
    }
    
    // Update selectedExercise with new custom media to reflect changes in ExercisesDetailDialog
    if (selectedExercise && selectedExercise.id === exerciseId) {
      setSelectedExercise({
        ...selectedExercise,
        customMedia: media || undefined
      })
    }
  }

  // Exercise Notes Management
  const handleSaveExerciseNote = (note: ExerciseNote) => {
    dataHelpers.updateExerciseNote(note)
    saveNoteToApi(note)
  }

  const handleDeleteExerciseNote = (noteId: string) => {
    const note = (exerciseNotes || []).find(n => n.id === noteId)
    if (note) {
      setNoteToDelete(note)
      setShowDeleteNoteDialog(true)
    }
  }

  const handleConfirmDeleteNote = () => {
    if (noteToDelete) {
      dataHelpers.deleteExerciseNote(noteToDelete.id)
      deleteNoteFromApi(noteToDelete.id)
      toast.success(t('exerciseNotes.noteDeleted'))
      setShowDeleteNoteDialog(false)
      setNoteToDelete(null)
    }
  }

  const handleCancelDeleteNote = () => {
    setShowDeleteNoteDialog(false)
    setNoteToDelete(null)
  }

  const handleExerciseNotesClick = (exercise: Exercise) => {
    setSelectedExercise(exercise)
    setShowExerciseNotesDialog(true)
  }

  const handleCloseExerciseNotesDialog = () => {
    setShowExerciseNotesDialog(false)
    // Don't clear selectedExercise here - let ExerciseDetailDialog handle it
  }

  // Personal Modifications Management
  const handleSavePersonalModification = (modification: PersonalModification) => {
    dataHelpers.updatePersonalModification(modification)
    saveModificationToApi(modification)
  }

  const handleDeletePersonalModification = (modificationId: string) => {
    const modification = (personalModifications || []).find(m => m.id === modificationId)
    if (modification) {
      setModificationToDelete(modification)
      setShowDeleteModificationDialog(true)
    }
  }

  const handleConfirmDeleteModification = () => {
    if (modificationToDelete) {
      dataHelpers.deletePersonalModification(modificationToDelete.id)
      deleteModificationFromApi(modificationToDelete.id)
      toast.success(t('personalModifications.modificationDeleted'))
      setShowDeleteModificationDialog(false)
      setModificationToDelete(null)
    }
  }

  const handleCancelDeleteModification = () => {
    setShowDeleteModificationDialog(false)
    setModificationToDelete(null)
  }

  const handlePersonalModificationsClick = (exercise: Exercise) => {
    setSelectedExercise(exercise)
    setShowPersonalModificationsDialog(true)
  }

  const handleClosePersonalModificationsDialog = () => {
    setShowPersonalModificationsDialog(false)
    // Don't clear selectedExercise here - let ExerciseDetailDialog handle it
  }

  // Get count of notes for an exercise
  const getExerciseNotesCount = (exerciseId: string) => {
    return dataHelpers.getExerciseNotesCount(exerciseId)
  }

  // Get count of active modifications for an exercise
  const getExerciseModificationsCount = (exerciseId: string) => {
    return dataHelpers.getExerciseModificationsCount(exerciseId)
  }
  const enhanceExerciseWithCustomMedia = (exercise: Exercise): Exercise => {
    const customMedia = (customExerciseMedia || {})[exercise.id]
    const translatedExercise = translateExercise(exercise)
    return {
      ...translatedExercise,
      customMedia
    }
  }

  // Favorite Exercise Management
  const handleToggleFavorite = (exercise: Exercise) => {
    const wasFavorite = dataHelpers.isExerciseFavorite(exercise.id)
    dataHelpers.toggleFavoriteExercise(exercise.id)
    
    // Sync with API
    if (wasFavorite) {
      removeFavoriteFromApi(exercise.id)
      toast.success(t('notifications.removedFromFavorites'))
    } else {
      const exerciseName = exercise.name || exercise.id
      addFavoriteToApi({
        exerciseId: exercise.id,
        favoritedAt: new Date().toISOString(),
      }, exerciseName)
      toast.success(t('notifications.addedToFavorites'))
    }
  }

  const isExerciseFavorite = (exerciseId: string) => {
    return dataHelpers.isExerciseFavorite(exerciseId)
  }

  // Gym Management Functions
  const handleSaveGym = (gym: GymType) => {
    dataHelpers.updateGym(gym)
    saveGymToApi(gym)
    toast.success(t('notifications.gymSaved'))
  }

  const handleDeleteGym = (gymId: string) => {
    const gym = (gyms || []).find(g => g.id === gymId)
    if (gym) {
      setGymToDelete(gym)
      setShowDeleteGymDialog(true)
    }
  }

  const handleConfirmDeleteGym = () => {
    if (gymToDelete) {
      dataHelpers.deleteGym(gymToDelete.id)
      deleteGymFromApi(gymToDelete.id)
      toast.success(t('notifications.gymDeleted'))
      setShowDeleteGymDialog(false)
      setGymToDelete(null)
    }
  }

  const handleCancelDeleteGym = () => {
    setShowDeleteGymDialog(false)
    setGymToDelete(null)
  }

  const handleSetActiveGym = (gymId: string) => {
    // Update local state
    dataHelpers.setActiveGym(gymId)
    
    // Sync all gyms with updated isActive status to API
    const updatedGyms = (gyms || []).map(gym => ({
      ...gym,
      isActive: gym.id === gymId
    }))
    
    // Sync the gym that is now active
    const activeGym = updatedGyms.find(g => g.id === gymId)
    if (activeGym) {
      saveGymToApi(activeGym)
    }
    
    // Sync previously active gym (now inactive)
    const previousActive = (gyms || []).find(g => g.isActive && g.id !== gymId)
    if (previousActive) {
      saveGymToApi({ ...previousActive, isActive: false })
    }
    
    toast.success(t('notifications.activeGymUpdated'))
  }

  const handleShowGymBuilder = (templateId?: string) => {
    setGymBuilderInitialTemplate(templateId)
    setShowGymBuilder(true)
  }

  const handleEditGym = (gym: GymType) => {
    setEditingGym(gym)
    setGymBuilderInitialTemplate(undefined)
    setShowGymBuilder(true)
  }

  const handleCloseGymBuilder = () => {
    setShowGymBuilder(false)
    setGymBuilderInitialTemplate(undefined)
    setEditingGym(undefined)
  }

  const handleCloseWorkoutSummary = () => {
    setShowWorkoutSummary(false)
    setCompletedWorkout(null)
    setWorkoutWasCompleted(false)
  }

  // Get active gym
  const getActiveGym = (): GymType | null => {
    return dataHelpers.getActiveGym()
  }

  // Get compatible exercises count for a gym
  const getGymCompatibleExercisesCount = (gym: GymType): number => {
    return gym.availableExerciseIds.length
  }

  // Personal Records Management
  const checkAndUpdatePersonalRecords = (completedWorkout: WorkoutHistory) => {
    const newRecords: PersonalRecord[] = []
    
    if (!completedWorkout.exercises || !Array.isArray(completedWorkout.exercises)) {
      return
    }
    
    completedWorkout.exercises.forEach(workoutExercise => {
      const exerciseId = workoutExercise.exerciseId

      // Check if exercise has sets before processing
      if (!workoutExercise.sets || !Array.isArray(workoutExercise.sets) || workoutExercise.sets.length === 0) {
        return
      }
      
      // Find the exercise in database to determine if it's time-based
      const exerciseData = exerciseDatabase.find(ex => ex.id === exerciseId)
      const isTimeBased = exerciseData?.setsConfigs?.primary === 'time'
      const hasWeight = exerciseData?.setsConfigs?.secondary === 'weight'
      
      // Get existing records for this exercise
      const existingRecords = (personalRecords || []).filter(pr => pr.exerciseId === exerciseId)
      
      if (isTimeBased) {
        // Handle time-based exercise records
        const maxTime = Math.max(...workoutExercise.sets.map(set => set.reps)) // reps field stores time for time-based exercises
        if (hasWeight) {
          // Time + Weight exercises (e.g., weighted plank)
          const maxTimeWeighted = workoutExercise.sets.reduce((best, set) => {
            if (set.reps > (best?.reps || 0)) return set
            if (set.reps === best?.reps && set.weight > (best?.weight || 0)) return set
            return best
          }, null as typeof workoutExercise.sets[0] | null)

          if (maxTimeWeighted) {
            const existingMaxTimeWeighted = existingRecords.find(pr => pr.type === 'maxTimeWeighted')
            if (!existingMaxTimeWeighted || 
                maxTimeWeighted.reps > (existingMaxTimeWeighted.duration || 0) ||
                (maxTimeWeighted.reps === (existingMaxTimeWeighted.duration || 0) && maxTimeWeighted.weight > (existingMaxTimeWeighted.weight || 0))) {
              newRecords.push({
                id: `${Date.now()}-${exerciseId}-timeweighted`,
                exerciseId,
                type: 'maxTimeWeighted',
                value: maxTimeWeighted.reps,
                weight: maxTimeWeighted.weight,
                duration: maxTimeWeighted.reps,
                measurementType: 'time',
                achievedAt: completedWorkout.completedAt,
                workoutHistoryId: completedWorkout.id
              })
            }
          }
        } else {
          // Time-only exercises (e.g., plank)
          const existingMaxTime = existingRecords.find(pr => pr.type === 'maxTime')
          if (!existingMaxTime || maxTime > (existingMaxTime.duration || 0)) {
            newRecords.push({
              id: `${Date.now()}-${exerciseId}-time`,
              exerciseId,
              type: 'maxTime',
              value: maxTime,
              duration: maxTime,
              measurementType: 'time',
              achievedAt: completedWorkout.completedAt,
              workoutHistoryId: completedWorkout.id
            })
          }
        }
      } else {
        // Handle reps-based exercise records (existing logic)
        const totalVolume = workoutExercise.sets.reduce((sum, set) => sum + (set.weight * set.reps), 0)

        // Find the heaviest single rep (estimated 1RM)
        const estimatedOneRepMax = Math.max(...workoutExercise.sets.map(set => {
          // Brzycki formula: weight * (36 / (37 - reps))
          return set.weight * (36 / (37 - set.reps))
        }))
        
        // Check for 1RM record
        const existing1RM = existingRecords.find(pr => pr.type === 'oneRepMax')
        if (!existing1RM || estimatedOneRepMax > existing1RM.value) {
          newRecords.push({
            id: `${Date.now()}-${exerciseId}-1rm`,
            exerciseId,
            type: 'oneRepMax',
            value: Math.round(estimatedOneRepMax),
            measurementType: 'reps',
            achievedAt: completedWorkout.completedAt,
            workoutHistoryId: completedWorkout.id
          })
        }
        
        // Check for volume record
        const existingVolume = existingRecords.find(pr => pr.type === 'maxVolume')
        if (!existingVolume || totalVolume > existingVolume.value) {
          newRecords.push({
            id: `${Date.now()}-${exerciseId}-volume`,
            exerciseId,
            type: 'maxVolume',
            value: totalVolume,
            measurementType: 'reps',
            achievedAt: completedWorkout.completedAt,
            workoutHistoryId: completedWorkout.id
          })
        }
        
        // Check for max reps record (at any weight)
        const heaviestHighRepSet = workoutExercise.sets.reduce((best, set) => {
          if (set.reps > (best?.reps || 0)) return set
          if (set.reps === best?.reps && set.weight > (best?.weight || 0)) return set
          return best
        }, null as typeof workoutExercise.sets[0] | null)

        if (heaviestHighRepSet) {
          const existingMaxReps = existingRecords.find(pr => pr.type === 'maxReps')
          if (!existingMaxReps || 
              heaviestHighRepSet.reps > (existingMaxReps.reps || 0) ||
              (heaviestHighRepSet.reps === (existingMaxReps.reps || 0) && heaviestHighRepSet.weight > (existingMaxReps.weight || 0))) {
            newRecords.push({
              id: `${Date.now()}-${exerciseId}-reps`,
              exerciseId,
              type: 'maxReps',
              value: heaviestHighRepSet.reps,
              weight: heaviestHighRepSet.weight,
              reps: heaviestHighRepSet.reps,
              measurementType: 'reps',
              achievedAt: completedWorkout.completedAt,
              workoutHistoryId: completedWorkout.id
            })
          }
        }
      }
    })
    
    if (newRecords.length > 0) {
      dataHelpers.updatePersonalRecords(newRecords)
      savePersonalRecordsToApi(newRecords) // Sync to API
      
      toast.success(newRecords.length > 1 ? t('notifications.newPersonalRecords') : t('notifications.newPersonalRecord'))
      
      // Send native push notification for personal records
      if (pwaSettings.achievements) {
        const firstRecord = newRecords[0]
        const localizedExerciseName =
          exerciseDataManager.getExerciseSync(language, firstRecord.exerciseId)?.name ??
          firstRecord.exerciseId
        showPersonalRecordNotification(
          localizedExerciseName,
          firstRecord.type,
          newRecords.length
        )
      }
    }
  }

  // User Profile Management
  const handleSaveUserData = (profile: UserData) => {
    dataSetters.setUserData(profile)
    toast.success(t('notifications.profileSaved'))
  }

  // Workout Goals Management
  const handleSaveWorkoutGoal = (goal: WorkoutGoal) => {
    dataHelpers.addWorkoutGoal(goal)
    saveGoalToApi(goal) // Sync to API
    toast.success(t('notifications.goalSaved'))
  }

  const handleUpdateWorkoutGoal = (goal: WorkoutGoal) => {
    dataHelpers.updateWorkoutGoal(goal)
    saveGoalToApi(goal) // Sync to API
    toast.success(t('notifications.goalUpdated'))
  }

  const handleDeleteWorkoutGoal = (goalId: string) => {
    const goal = (workoutGoals || []).find(g => g.id === goalId)
    if (goal) {
      setGoalToDelete(goal)
      setShowWorkoutGoalDeleteDialog(true)
    }
  }

  const handleConfirmDeleteWorkoutGoal = () => {
    if (goalToDelete) {
      dataHelpers.deleteWorkoutGoal(goalToDelete.id)
      deleteGoalFromApi(goalToDelete.id) // Delete from API
      toast.success(t('notifications.goalDeleted'))
      setShowWorkoutGoalDeleteDialog(false)
      setGoalToDelete(null)
    }
  }

  const handleCancelDeleteWorkoutGoal = () => {
    setShowWorkoutGoalDeleteDialog(false)
    setGoalToDelete(null)
  }

  // Achievements Management
  const handleCreateAchievement = (achievement: Achievement) => {
    dataHelpers.addAchievement(achievement)
    saveAchievementToApi(achievement) // Sync to API
    createAchievementNotification(achievement)
    
    // Show PWA notification for achievement
    if (pwaSettings.achievements) {
      showAchievementNotification(achievement.title, achievement.description || '')
    }
    
    toast.success(t('notifications.achievementUnlocked'))
  }

  // Stats calculations with filtering
  const currentProgressPeriod = progressPreferences?.period

  // Calculate unique exercises used in workout history
  const uniqueExercisesInHistory = useMemo(() => {
    const uniqueIds = new Set<string>()
    ;(workoutHistory || []).forEach(history => {
      history.exercises?.forEach(ex => {
        if (ex.exerciseId) uniqueIds.add(ex.exerciseId)
      })
    })
    return uniqueIds
  }, [workoutHistory])

  // Calculate exercise popularity based on usage frequency, favorites, and built-in status
  // When user has < 30 unique exercises in history, built-in exercises get a bonus
  // to provide better recommendations for new users
  const getExercisePopularity = (exerciseId: string) => {
    const workoutUsage = (workoutHistory || []).reduce((count, history) => {
      return count + (history.exercises?.filter(ex => ex.exerciseId === exerciseId).length || 0)
    }, 0)
    
    const isFavorited = isExerciseFavorite(exerciseId) ? 10 : 0 // Bonus points for being favorited
    
    // Built-in bonus only applies when user has less than 30 unique exercises in history
    const builtInBonus = uniqueExercisesInHistory.size < 30 && isBuiltInExercise(exerciseId) ? 5 : 0
    
    return workoutUsage + isFavorited + builtInBonus
  }

  // Show auth loading
  if (authLoading) {
    return (
      <div className="min-h-screen bg-background flex items-center justify-center">
        <div className="flex flex-col items-center gap-4">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
          <p className="text-muted-foreground">{t('common.loading') || 'Loading...'}</p>
        </div>
      </div>
    )
  }

  // Note: OAuth callback is handled by routes/index.tsx route, not here

  // Show auth screen if not authenticated
  if (!isAuthenticated && !isGuest) {
    return <AuthScreen />
  }

  // Show welcome screen if needed (must be after all hooks)
  // Show loading spinner while IndexedDB initializes
  if (userWelcomeCompleted === undefined) {
    return (
      <div className="min-h-screen bg-background flex items-center justify-center">
        <div className="flex flex-col items-center gap-4">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
          <p className="text-muted-foreground">{t('common.loading') || 'Loading...'}</p>
        </div>
      </div>
    )
  }

  if (!userWelcomeCompleted && welcomeDelayPassed) {
    return (
      <AppUserWelcome
        onComplete={handleUserWelcomeComplete}
        onSkip={handleUserWelcomeSkip}
      />
    )
  }

  // Show loading while waiting for welcome delay
  if (!userWelcomeCompleted && !welcomeDelayPassed) {
    return (
      <div className="min-h-screen bg-background flex items-center justify-center">
        <div className="flex flex-col items-center gap-4">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
          <p className="text-muted-foreground">{t('common.loading') || 'Loading...'}</p>
        </div>
      </div>
    )
  }

  if (activeSession) {
    const exercises = (activeSession.workout.exercises || [])
    const currentExercise = exercises[currentExerciseIndex]
    // Progress based on actually completed exercises (all sets completed)
    const completedExercisesCount = exercises.filter(ex => {
      const sets = ex.sets || []
      return sets.length > 0 && sets.every(s => s.completed)
    }).length
    const progress = exercises.length > 0 ? (completedExercisesCount / exercises.length) * 100 : 0
    const hasSkippedExercises = exercises.some((ex, idx) => {
      if (idx === currentExerciseIndex) return false
      return (ex.sets || []).some(set => !set.completed)
    })

    return (
      <div className="min-h-screen bg-background pb-14">
        <div className="container mx-auto p-4 max-w-2xl">
          <div className="mb-6">
            <div className="flex items-center justify-between mb-4">
              <h1 className="text-2xl font-bold">{activeSession.workout.name}</h1>
              <Button variant="destructive" onClick={handleStopWorkout} className="haptic-feedback" data-testid="stop-workout-button">
                {t('activeWorkout.stopWorkout')}
              </Button>
            </div>
            <div className="space-y-2">
              <div className="flex justify-between text-sm text-muted-foreground">
                <span>{t('activeWorkout.exercise')} {currentExerciseIndex + 1} {t('activeWorkout.of')} {(activeSession.workout.exercises || []).length}</span>
                <span>{Math.round(progress)}% {t('activeWorkout.complete')}</span>
              </div>
              <ProgressBar value={progress} className="h-2" />
            </div>
          </div>

          {currentExercise && (
            <WorkoutActiveExercise
              key={`${currentExercise.exerciseId}-${currentExerciseIndex}`}
              workoutExercise={currentExercise}
              personalRecords={personalRecords || []}
              onSetComplete={handleSetComplete}
              onNext={handleNextExercise}
              onPrev={handlePrevExercise}
              onViewDetails={handleViewExerciseDetails}
              isLast={currentExerciseIndex === (activeSession.workout.exercises || []).length - 1}
              isFirst={currentExerciseIndex === 0}
              hasSkippedExercises={hasSkippedExercises}
            />
          )}
        </div>

        <WorkoutCancelDialog
          open={showCancelWorkoutDialog}
          onConfirm={handleCancelWorkoutConfirm}
          onCancel={handleCancelWorkoutCancel}
          workoutName={cancelWorkoutName}
        />

        <ExercisesDetailDialog
          exercise={selectedExercise}
          open={showExerciseDetail}
          onClose={handleCloseExerciseDetail}
          personalRecords={personalRecords || []}
          workoutHistory={workoutHistory || []}
          onCustomMediaClick={isGuest 
            ? (exercise) => handleGuestPremiumFeatureClick('customMedia', exercise)
            : handleCustomMediaClick
          }
          onNotesClick={handleExerciseNotesClick}
          onModificationsClick={handlePersonalModificationsClick}
          getExerciseNotesCount={getExerciseNotesCount}
          getExerciseModificationsCount={getExerciseModificationsCount}
        />

        <ExercisesCustomMediaDialog
          open={showCustomMediaDialog}
          onClose={handleCloseCustomMediaDialog}
          exercise={selectedExercise}
          onSaveMedia={handleSaveCustomMedia}
          onUploadMedia={uploadAndSyncMedia}
        />

        <ExercisesNotesDialog
          open={showExerciseNotesDialog}
          onClose={handleCloseExerciseNotesDialog}
          exercise={selectedExercise}
          exerciseNotes={exerciseNotes || []}
          onSaveNote={handleSaveExerciseNote}
          onDeleteNote={handleDeleteExerciseNote}
        />

        <ExercisesPersonalModificationsDialog
          open={showPersonalModificationsDialog}
          onClose={handleClosePersonalModificationsDialog}
          exercise={selectedExercise}
          personalModifications={personalModifications || []}
          onSaveModification={handleSavePersonalModification}
          onDeleteModification={handleDeletePersonalModification}
        />

        <PremiumFeaturePaywall
          open={showPremiumPaywall}
          onClose={handleClosePremiumPaywall}
          feature={premiumPaywallFeature}
          onSignIn={handlePaywallSignIn}
          onSignUp={handlePaywallSignUp}
        />
        <AdBanner 
          onAdFailedToLoad={handleAdFailedToLoad}
        />
      </div>
    )
  }

  return (
    <div className="min-h-screen bg-background main-content-mobile-padding">
      <AppUpdateAvailableDialog />
      <AppLanguageAutoDetectionNotifier />
      <ExerciseCatalogUpdateIndicator />
      <div className="container mx-auto p-4 max-w-4xl">
        {/* PWA Install Prompt */}
        {showPWAInstallPrompt && (
          <div className="mb-6">
            <AppPWAInstallPrompt onClose={handleClosePWAInstallPrompt} />
          </div>
        )}

        <header className="mb-8">
          <div className="flex items-center justify-between">
            <Button 
              variant="outline" 
              className="text-2xl font-bold p-0 h-auto hover:bg-transparent hover:text-primary transition-colors px-3 haptic-feedback"
              onClick={() => setShowAppInfoDialog(true)}
            >
              <div className="flex items-center gap-2">
                <img 
                  src={logoSrc} 
                  alt={BRANDING.appName} 
                  className={BRANDING.onlyLogo ? "h-8 w-auto object-contain" : "w-6 h-6 flex-shrink-0"}
                  style={BRANDING.onlyLogo && BRANDING.logoPadding ? { padding: `${BRANDING.logoPadding}px` } : undefined}
                />
                {!BRANDING.onlyLogo && <span>{BRANDING.appName}</span>}
              </div>
            </Button>
            <div className="flex items-center gap-2">
              {user && (
                <div className="hidden sm:flex items-center gap-2 text-sm text-muted-foreground mr-2">
                  <UserIcon className="h-4 w-4" />
                  <span>{user.name}</span>
                </div>
              )}
              {user?.role === 'ADMIN' && (
                <UserAdminPanel currentUserId={user?.id} />
              )}
              {user?.role === 'TRAINER' && (
                <TrainerPanel 
                  activeStudent={activeTrainerStudent}
                  onSelectStudent={handleSelectTrainerStudent}
                  onDeselectStudent={handleExitStudentMode}
                  onNavigateToTab={handleNavigateToTab}
                />
              )}
              <AppNotificationPanel
                notifications={getVisibleNotifications()}
                unreadCount={getUnreadCount()}
                onMarkAsRead={markAsRead}
                onMarkAsUnread={markAsUnread}
                onToggleReadStatus={toggleReadStatus}
                onArchive={archiveNotification}
                onDelete={deleteNotification}
                onMarkAllAsRead={markAllAsRead}
                onClearAll={clearAllNotifications}
                onNotificationAction={handleNotificationAction}
              />
            </div>
          </div>
        </header>

        {/* Email Verification Banner */}
        <AppEmailVerificationBanner />

        <Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-6">
          {/* Desktop Tabs */}
          <TabsList className="hidden sm:flex w-full p-[2px] gap-0">
            <TabsTrigger value="gym" className="flex items-center justify-center gap-2 flex-1 px-3 desktop-tab-feedback">
              <MapPin className="h-4 w-4 flex-shrink-0" />
              <span className="hidden md:inline whitespace-nowrap">
                {t('tabs.gyms')}
              </span>
              {activeTab === 'gym' && <span className="md:hidden text-xs">{t('tabs.gyms')}</span>}
            </TabsTrigger>
            <TabsTrigger value="exercises" className="flex items-center justify-center gap-2 flex-1 px-3 desktop-tab-feedback">
              <BookOpen className="h-4 w-4 flex-shrink-0" />
              <span className="hidden md:inline whitespace-nowrap">
                {t('tabs.exercises')}
              </span>
              {activeTab === 'exercises' && <span className="md:hidden text-xs">{t('tabs.exercises')}</span>}
            </TabsTrigger>
            <TabsTrigger value="workouts" className="flex items-center justify-center gap-2 flex-1 px-3 desktop-tab-feedback">
              <Barbell className="h-4 w-4 flex-shrink-0" />
              <span className="hidden md:inline whitespace-nowrap">
                {t('tabs.workouts')}
              </span>
              {activeTab === 'workouts' && <span className="md:hidden text-xs">{t('tabs.workouts')}</span>}
            </TabsTrigger>
            <TabsTrigger value="progress" className="flex items-center justify-center gap-2 flex-1 px-3 desktop-tab-feedback">
              <TrendUp className="h-4 w-4 flex-shrink-0" />
              <span className="hidden md:inline whitespace-nowrap">
                {t('tabs.progress')}
              </span>
              {activeTab === 'progress' && <span className="md:hidden text-xs">{t('tabs.progress')}</span>}
            </TabsTrigger>
            <TabsTrigger value="user" className="flex items-center justify-center gap-2 flex-1 px-3 desktop-tab-feedback">
              <UserIcon className="h-4 w-4 flex-shrink-0" />
              <span className="hidden md:inline whitespace-nowrap">
                {t('tabs.user')}
              </span>
              {activeTab === 'user' && <span className="md:hidden text-xs">{t('tabs.user')}</span>}
            </TabsTrigger>
          </TabsList>

          <TabsContent value="gym" className="space-y-6">
            <Gym
              gyms={gyms || []}
              gymDistances={gymDistances}
              isLoadingDistances={isLoadingDistances}
              onShowGymBuilder={handleShowGymBuilder}
              onEditGym={handleEditGym}
              onDeleteGym={handleDeleteGym}
              onSetActiveGym={handleSetActiveGym}
              getActiveGym={getActiveGym}
              getGymCompatibleExercisesCount={getGymCompatibleExercisesCount}
            />
          </TabsContent>
          <TabsContent value="exercises" className="space-y-6">
            <Exercises
              exerciseDisplayMode={exerciseDisplayMode || 'card'}
              favoriteExercises={favoriteExercises || []}
              sortPreferences={sortPreferences || null}
              onExerciseDisplayModeChange={setExerciseDisplayMode}
              onUpdateExerciseSort={updateExerciseSort}
              onToggleExerciseSortReverse={toggleExerciseSortReverse}
              onViewExerciseDetails={handleViewExerciseDetails}
              onToggleFavorite={handleToggleFavorite}
              isExerciseFavorite={isExerciseFavorite}
              getExerciseNotesCount={getExerciseNotesCount}
              getExerciseModificationsCount={getExerciseModificationsCount}
              getExercisePopularity={getExercisePopularity}
              getActiveGym={getActiveGym}
            />
          </TabsContent>
          <TabsContent value="workouts" className="space-y-6">
            <Workouts
              workouts={workouts || []}
              workoutHistory={workoutHistory || []}
              personalRecords={personalRecords || []}
              userData={userData || null}
              favoriteExercises={favoriteExercises || []}
              sortPreferences={sortPreferences || null}
              onStartWorkout={handleStartWorkout}
              onSaveWorkout={handleSaveWorkout}
              onDeleteWorkout={handleDeleteWorkout}
              onViewExerciseDetails={handleViewExerciseDetails}
              onToggleFavorite={handleToggleFavorite}
              onUpdateWorkoutSort={updateWorkoutSort}
              onToggleWorkoutSortReverse={toggleWorkoutSortReverse}
              activeStudent={activeTrainerStudent}
              onExitStudentMode={handleExitStudentMode}
              onSwitchToProgress={() => handleNavigateToTab('progress')}
            />
          </TabsContent>
          <TabsContent value="progress" className="space-y-6">
            <ProgressTab
              workoutGoals={workoutGoals || []}
              workoutHistory={workoutHistory || []}
              personalRecords={personalRecords || []}
              currentProgressPeriod={currentProgressPeriod}
              onUpdateWorkoutGoal={handleUpdateWorkoutGoal}
              onCreateAchievement={handleCreateAchievement}
              onUpdateProgressPeriod={updateProgressPeriod}
              activeStudent={activeTrainerStudent}
              onExitStudentMode={handleExitStudentMode}
              onSwitchToWorkouts={() => handleNavigateToTab('workouts')}
            />
          </TabsContent>
          <TabsContent value="user" className="space-y-6">
            <User
              userData={userData || null}
              onSave={handleSaveUserData}
              onShowGoals={() => setShowWorkoutGoalsDialog(true)}
              onShowAchievements={() => setShowUserAchievementsDialog(true)}
            />
          </TabsContent>
        </Tabs>

        <ExercisesDetailDialog
          exercise={selectedExercise}
          open={showExerciseDetail}
          onClose={handleCloseExerciseDetail}
          personalRecords={personalRecords || []}
          workoutHistory={workoutHistory || []}
          onCustomMediaClick={isGuest 
            ? (exercise) => handleGuestPremiumFeatureClick('customMedia', exercise)
            : handleCustomMediaClick
          }
          onNotesClick={handleExerciseNotesClick}
          onModificationsClick={handlePersonalModificationsClick}
          getExerciseNotesCount={getExerciseNotesCount}
          getExerciseModificationsCount={getExerciseModificationsCount}
        />

        <ExercisesCustomMediaDialog
          open={showCustomMediaDialog}
          onClose={handleCloseCustomMediaDialog}
          exercise={selectedExercise}
          onSaveMedia={handleSaveCustomMedia}
          onUploadMedia={uploadAndSyncMedia}
        />

        <GymBuilder
          open={showGymBuilder}
          onClose={handleCloseGymBuilder}
          onSave={handleSaveGym}
          gym={editingGym}
          initialTemplate={gymBuilderInitialTemplate}
        />

        <WorkoutSummaryDialog
          open={showWorkoutSummary}
          onClose={handleCloseWorkoutSummary}
          workoutHistory={completedWorkout}
          personalRecords={personalRecords || []}
          wasCompleted={workoutWasCompleted}
          userData={userData}
          onViewExerciseDetails={handleViewExerciseDetails}
          shareEnabled
        />

        <ExercisesNotesDialog
          open={showExerciseNotesDialog}
          onClose={handleCloseExerciseNotesDialog}
          exercise={selectedExercise}
          exerciseNotes={exerciseNotes || []}
          onSaveNote={handleSaveExerciseNote}
          onDeleteNote={handleDeleteExerciseNote}
        />

        <ExercisesPersonalModificationsDialog
          open={showPersonalModificationsDialog}
          onClose={handleClosePersonalModificationsDialog}
          exercise={selectedExercise}
          personalModifications={personalModifications || []}
          onSaveModification={handleSavePersonalModification}
          onDeleteModification={handleDeletePersonalModification}
        />

        <WorkoutCancelDialog
          open={showCancelWorkoutDialog}
          onConfirm={handleCancelWorkoutConfirm}
          onCancel={handleCancelWorkoutCancel}
          workoutName={cancelWorkoutName}
        />

        <GymDeleteDialog
          open={showDeleteGymDialog}
          onConfirm={handleConfirmDeleteGym}
          onCancel={handleCancelDeleteGym}
          gym={gymToDelete}
        />

        <ExercisesNoteDeleteDialog
          open={showDeleteNoteDialog}
          onConfirm={handleConfirmDeleteNote}
          onCancel={handleCancelDeleteNote}
          note={noteToDelete}
        />

        <ExercisesPersonalModificationDeleteDialog
          open={showDeleteModificationDialog}
          onConfirm={handleConfirmDeleteModification}
          onCancel={handleCancelDeleteModification}
          modification={modificationToDelete}
        />

        <WorkoutGoalsDialog
          open={showWorkoutGoalsDialog}
          onClose={() => setShowWorkoutGoalsDialog(false)}
          goals={workoutGoals || []}
          onSaveGoal={handleSaveWorkoutGoal}
          onDeleteGoal={handleDeleteWorkoutGoal}
          onUpdateGoal={handleUpdateWorkoutGoal}
          personalRecords={personalRecords || []}
          userData={userData}
        />

        <WorkoutGoalDeleteDialog
          open={showWorkoutGoalDeleteDialog}
          onConfirm={handleConfirmDeleteWorkoutGoal}
          onCancel={handleCancelDeleteWorkoutGoal}
          goal={goalToDelete}
        />

        <UserAchievementsDialog
          open={showUserAchievementsDialog}
          onClose={() => setShowUserAchievementsDialog(false)}
          achievements={achievements || []}
        />

        <WorkoutHistoryDialog
          open={showWorkoutHistoryDialog}
          onClose={() => setShowWorkoutHistoryDialog(false)}
          workoutHistory={workoutHistory || []}
        />

        <AppInfoDialog
          open={showAppInfoDialog}
          onClose={() => setShowAppInfoDialog(false)}
        />

        <PremiumFeaturePaywall
          open={showPremiumPaywall}
          onClose={handleClosePremiumPaywall}
          feature={premiumPaywallFeature}
          onSignIn={handlePaywallSignIn}
          onSignUp={handlePaywallSignUp}
        />
      </div>

      {/* Mobile Fixed Footer Navigation */}
      <div 
        className="sm:hidden fixed left-0 right-0 bg-background border-t border-border z-50" 
        style={{ 
          bottom: 0,
          paddingBottom: 'env(safe-area-inset-bottom)' 
        }}
      >
        <div className="flex items-center justify-around px-2 py-2">
          <button
            onClick={() => setActiveTab('gym')}
            className={`flex flex-col items-center gap-1 p-3 rounded-lg transition-colors mobile-tab-feedback ${activeTab === 'gym'
                ? 'text-primary bg-primary/10'
                : 'text-muted-foreground hover:text-foreground hover:bg-accent/50'
              }`}
          >
            <MapPin className="h-5 w-5" />
            {activeTab === 'gym' && <span className="text-xs">{t('tabs.gyms')}</span>}
          </button>
          <button
            onClick={() => setActiveTab('exercises')}
            className={`flex flex-col items-center gap-1 p-3 rounded-lg transition-colors mobile-tab-feedback ${
              activeTab === 'exercises' 
                ? 'text-primary bg-primary/10' 
                : 'text-muted-foreground hover:text-foreground hover:bg-accent/50'
            }`}
          >
            <BookOpen className="h-5 w-5" />
            {activeTab === 'exercises' && <span className="text-xs">{t('tabs.exercises')}</span>}
          </button>
          <button
            onClick={() => setActiveTab('workouts')}
            className={`flex flex-col items-center gap-1 p-3 rounded-lg transition-colors mobile-tab-feedback ${activeTab === 'workouts'
                ? 'text-primary bg-primary/10'
                : 'text-muted-foreground hover:text-foreground hover:bg-accent/50'
              }`}
          >
            <Barbell className="h-5 w-5" />
            {activeTab === 'workouts' && <span className="text-xs">{t('tabs.workouts')}</span>}
          </button>
          <button
            onClick={() => setActiveTab('progress')}
            className={`flex flex-col items-center gap-1 p-3 rounded-lg transition-colors mobile-tab-feedback ${
              activeTab === 'progress' 
                ? 'text-primary bg-primary/10' 
                : 'text-muted-foreground hover:text-foreground hover:bg-accent/50'
            }`}
          >
            <TrendUp className="h-5 w-5" />
            {activeTab === 'progress' && <span className="text-xs">{t('tabs.progress')}</span>}
          </button>
          <button
            onClick={() => setActiveTab('user')}
            className={`flex flex-col items-center gap-1 p-3 rounded-lg transition-colors mobile-tab-feedback ${
              activeTab === 'user' 
                ? 'text-primary bg-primary/10' 
                : 'text-muted-foreground hover:text-foreground hover:bg-accent/50'
            }`}
          >
            <UserIcon className="h-5 w-5" />
            {activeTab === 'user' && <span className="text-xs">{t('tabs.user')}</span>}
          </button>
        </div>
      </div>
    </div>
  )
}

function App() {
  return (
    <I18nProvider>
      <AppContent />
    </I18nProvider>
  )
}

export default App