import React, { useState, useEffect, useCallback, useRef } from 'react'
import CurrentWeek from './components/CurrentWeek'
import FullStatistics from './components/FullStatistics'
import ProjectPriorityManager from './components/ProjectPriorityManager'
import WordList from './components/WordList'
import AddWords from './components/AddWords'
import DictionaryList from './components/DictionaryList'
import TestWords from './components/TestWords'
import Profile from './components/Profile'
import TaskList from './components/TaskList'
import TaskForm from './components/TaskForm.jsx'
import Wishlist from './components/Wishlist'
import WishlistForm from './components/WishlistForm'
import WishlistDetail from './components/WishlistDetail'
import BoardForm from './components/BoardForm'
import BoardJoinPreview from './components/BoardJoinPreview'
import ShoppingList from './components/ShoppingList'
import ShoppingItemForm from './components/ShoppingItemForm'
import ShoppingBoardForm from './components/ShoppingBoardForm'
import ShoppingBoardJoinPreview from './components/ShoppingBoardJoinPreview'
import ShoppingItemHistory from './components/ShoppingItemHistory'
import PurchaseScreen from './components/PurchaseScreen'
import TodoistIntegration from './components/TodoistIntegration'
import TelegramIntegration from './components/TelegramIntegration'
import FitbitIntegration from './components/FitbitIntegration'
import Tracking from './components/Tracking'
import TrackingAccess from './components/TrackingAccess'
import TrackingInviteAccept from './components/TrackingInviteAccept'
import { AuthProvider, useAuth } from './components/auth/AuthContext'
import AuthScreen from './components/auth/AuthScreen'
import PWAUpdatePrompt from './components/PWAUpdatePrompt'

// API endpoints (используем относительные пути, проксирование настроено в nginx/vite)
const CURRENT_WEEK_API_URL = '/playlife-feed'
const FULL_STATISTICS_API_URL = '/d2dc349a-0d13-49b2-a8f0-1ab094bfba9b'

// Определяем основные табы (без крестика) и глубокие табы (с крестиком)
const mainTabs = ['current', 'tasks', 'wishlist', 'profile']
const deepTabs = ['add-words', 'test', 'purchase', 'task-form', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'full', 'priorities', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']

/**
 * Гарантирует базовую запись истории для главного экрана перед глубоким табом.
 * После долгого бездействия PWA может перезапуститься с одной записью в истории;
 * кнопка "назад" тогда закрывает приложение. Эта функция добавляет запись для
 * экрана 'current', чтобы "назад" возвращала на главный экран.
 */
function ensureBaseHistory(deepTab, params = {}, url) {
  if (typeof window === 'undefined' || !deepTabs.includes(deepTab)) return
  if (window.history.length <= 1) {
    window.history.replaceState({ tab: 'current' }, '', '/')
    window.history.pushState({ tab: deepTab, params, previousTab: 'current' }, '', url)
  } else {
    window.history.replaceState({ tab: deepTab, params, previousTab: 'current' }, '', url)
  }
}

function AppContent() {
  const { authFetch, isAuthenticated, loading: authLoading } = useAuth()
  const prevIsAuthenticatedRef = useRef(null)
  
  // Все хуки должны быть объявлены до условных возвратов
  const [activeTab, setActiveTab] = useState('current')
  const [selectedProject, setSelectedProject] = useState(null)
  const [loadedTabs, setLoadedTabs] = useState({
    current: false,
    priorities: false,
    full: false,
    words: false,
    'add-words': false,
    dictionaries: false,
    test: false,
    tasks: false,
    'task-form': false,
    wishlist: false,
    'wishlist-form': false,
    'wishlist-detail': false,
    'board-form': false,
    'board-join': false,
    profile: false,
    'todoist-integration': false,
    'telegram-integration': false,
    'fitbit-integration': false,
    tracking: false,
    'tracking-access': false,
    'tracking-invite': false,
    shopping: false,
    'shopping-item-form': false,
    'shopping-board-form': false,
    'shopping-board-join': false,
    'shopping-item-history': false,
    purchase: false,
  })

  // Отслеживаем, какие табы уже были загружены (для предотвращения повторных загрузок)
  const [tabsInitialized, setTabsInitialized] = useState({
    current: false,
    priorities: false,
    full: false,
    words: false,
    'add-words': false,
    dictionaries: false,
    test: false,
    tasks: false,
    'task-form': false,
    wishlist: false,
    'wishlist-form': false,
    'wishlist-detail': false,
    'board-form': false,
    'board-join': false,
    profile: false,
    'todoist-integration': false,
    'telegram-integration': false,
    'fitbit-integration': false,
    tracking: false,
    'tracking-access': false,
    'tracking-invite': false,
    shopping: false,
    'shopping-item-form': false,
    'shopping-board-form': false,
    'shopping-board-join': false,
    'shopping-item-history': false,
    purchase: false,
  })

  // Параметры для навигации между вкладками
  const [tabParams, setTabParams] = useState({})
  
  // Предыдущий таб для возврата из модальных окон
  const [previousTab, setPreviousTab] = useState(null)

  // Счётчик для сброса формы товара при каждом открытии
  const [shoppingItemFormKey, setShoppingItemFormKey] = useState(0)

  // Ref для функции открытия модала добавления записи в CurrentWeek
  const currentWeekAddModalRef = useRef(null)

  // Подтверждение приоритетов на текущей неделе (null = неизвестно, true/false = известно)
  const [prioritiesConfirmed, setPrioritiesConfirmed] = useState(null)
  const prioritiesOverlayPushedRef = useRef(false)

  // Кеширование данных
  const [currentWeekData, setCurrentWeekData] = useState(null)
  const [fullStatisticsData, setFullStatisticsData] = useState(null)
  const [tasksData, setTasksData] = useState(null)
  const [todayEntriesData, setTodayEntriesData] = useState(null)
  
  // Состояния загрузки для каждого таба (показываются только при первой загрузке)
  const [currentWeekLoading, setCurrentWeekLoading] = useState(false)
  const [fullStatisticsLoading, setFullStatisticsLoading] = useState(false)
  const [prioritiesLoading, setPrioritiesLoading] = useState(false)
  const [tasksLoading, setTasksLoading] = useState(false)
  const [todayEntriesLoading, setTodayEntriesLoading] = useState(false)
  
  // Состояния фоновой загрузки (не показываются визуально)
  const [currentWeekBackgroundLoading, setCurrentWeekBackgroundLoading] = useState(false)
  const [fullStatisticsBackgroundLoading, setFullStatisticsBackgroundLoading] = useState(false)
  const [prioritiesBackgroundLoading, setPrioritiesBackgroundLoading] = useState(false)
  const [tasksBackgroundLoading, setTasksBackgroundLoading] = useState(false)
  const [todayEntriesBackgroundLoading, setTodayEntriesBackgroundLoading] = useState(false)
  
  // Ошибки
  const [currentWeekError, setCurrentWeekError] = useState(null)
  const [fullStatisticsError, setFullStatisticsError] = useState(null)
  const [prioritiesError, setPrioritiesError] = useState(null)
  const [tasksError, setTasksError] = useState(null)
  const [todayEntriesError, setTodayEntriesError] = useState(null)
  
  // Состояние для кнопки Refresh (если она есть)
  const [isRefreshing, setIsRefreshing] = useState(false)
  const [prioritiesRefreshTrigger, setPrioritiesRefreshTrigger] = useState(0)
  const [dictionariesRefreshTrigger, setDictionariesRefreshTrigger] = useState(0)
  const [wordsRefreshTrigger, setWordsRefreshTrigger] = useState(0)
  const [wishlistRefreshTrigger, setWishlistRefreshTrigger] = useState(0)
  const [shoppingRefreshTrigger, setShoppingRefreshTrigger] = useState(0)



  // Восстанавливаем последний выбранный таб после перезагрузки
  const [isInitialized, setIsInitialized] = useState(false)

  // Управление историей для оверлея приоритетов
  useEffect(() => {
    const overlayVisible = activeTab === 'current' && prioritiesConfirmed === false
    if (overlayVisible && !prioritiesOverlayPushedRef.current) {
      prioritiesOverlayPushedRef.current = true
      // Заменяем текущую запись { tab: 'current' } на { tab: 'tasks' },
      // затем добавляем запись оверлея. Так системная кнопка "Назад" вернёт на tasks.
      window.history.replaceState({ tab: 'tasks' }, '', '/')
      window.history.pushState({ tab: 'current', prioritiesOverlay: true }, '', '/')
    }
    if (!overlayVisible) {
      prioritiesOverlayPushedRef.current = false
    }
  }, [activeTab, prioritiesConfirmed])

  // Переключение на экран прогрессии после успешной авторизации
  useEffect(() => {
    // Обновляем ref только после того, как authLoading стал false
    if (!authLoading) {
      const wasNotAuthenticated = prevIsAuthenticatedRef.current === false

      // Обновляем ref только если инициализация завершена,
      // чтобы не потерять переход false→true при ожидании isInitialized
      if (isInitialized) {
        prevIsAuthenticatedRef.current = isAuthenticated
      }

      // Проверяем, что это новая авторизация (переход с false на true)
      // и что инициализация уже завершена (чтобы не конфликтовать с восстановлением из URL/localStorage)
      if (wasNotAuthenticated && isAuthenticated && isInitialized) {
        // Сбрасываем ошибки, кеш данных и состояние инициализации табов при повторной авторизации
        setCurrentWeekError(null)
        setFullStatisticsError(null)
        setPrioritiesError(null)
        setTasksError(null)
        setTodayEntriesError(null)
        setCurrentWeekData(null)
        setFullStatisticsData(null)
        setTasksData(null)
        setTodayEntriesData(null)
        setPrioritiesConfirmed(null)
        // Сбрасываем инициализацию табов, чтобы данные загрузились заново
        Object.keys(tabsInitializedRef.current).forEach(key => {
          tabsInitializedRef.current[key] = false
        })
        cacheRef.current = { current: null, full: null, tasks: null, todayEntries: null }
        lastLoadedTabRef.current = null

        // Переключаемся на экран прогресса только если нет таба в URL
        const urlParams = new URLSearchParams(window.location.search)
        const tabFromUrl = urlParams.get('tab')

        // Если в URL нет таба, переключаемся на current (экран прогресса)
        if (!tabFromUrl) {
          setActiveTab('current')
          setLoadedTabs(prev => ({ ...prev, current: true }))
          // Очищаем URL, так как current - это основной таб
          const url = new URL(window.location)
          url.searchParams.delete('tab')
          url.searchParams.forEach((value, key) => {
            url.searchParams.delete(key)
          })
          window.history.replaceState({ tab: 'current' }, '', url)
        }
      }
    }
  }, [isAuthenticated, isInitialized, authLoading])
  
  // Инициализация из URL (только для глубоких табов) или localStorage
  useEffect(() => {
    if (isInitialized) return
    
    try {
      // Проверяем путь /invite/:token для присоединения к доске
      const path = window.location.pathname
      if (path.startsWith('/invite/')) {
        const token = path.replace('/invite/', '')
        if (token) {
          const url = '/?tab=board-join&inviteToken=' + token
          ensureBaseHistory('board-join', { inviteToken: token }, url)
          setActiveTab('board-join')
          setLoadedTabs(prev => ({ ...prev, 'board-join': true }))
          setTabParams({ inviteToken: token })
          setIsInitialized(true)
          return
        }
      }

      // Проверяем путь /shopping-invite/:token для присоединения к shopping доске
      if (path.startsWith('/shopping-invite/')) {
        const token = path.replace('/shopping-invite/', '')
        if (token) {
          const url = '/?tab=shopping-board-join&inviteToken=' + token
          ensureBaseHistory('shopping-board-join', { inviteToken: token }, url)
          setActiveTab('shopping-board-join')
          setLoadedTabs(prev => ({ ...prev, 'shopping-board-join': true }))
          setTabParams({ inviteToken: token })
          setIsInitialized(true)
          return
        }
      }

      // Проверяем путь /tracking/invite/:token
      if (path.startsWith('/tracking/invite/')) {
        const token = path.replace('/tracking/invite/', '')
        if (token) {
          const url = '/?tab=tracking-invite&inviteToken=' + token
          ensureBaseHistory('tracking-invite', { inviteToken: token }, url)
          setActiveTab('tracking-invite')
          setLoadedTabs(prev => ({ ...prev, 'tracking-invite': true }))
          setTabParams({ inviteToken: token })
          setIsInitialized(true)
          return
        }
      }

      // Проверяем параметры OAuth callback от Fitbit
      const urlParams = new URLSearchParams(window.location.search)
      const integration = urlParams.get('integration')
      if (integration === 'fitbit') {
        const status = urlParams.get('status')
        const message = urlParams.get('message')
        let newUrl = '/?tab=fitbit-integration&integration=fitbit'
        if (status) newUrl += `&status=${status}`
        if (message) newUrl += `&message=${message}`
        const fitbitParams = { integration: 'fitbit' }
        if (status) fitbitParams.status = status
        if (message) fitbitParams.message = message
        ensureBaseHistory('fitbit-integration', fitbitParams, newUrl)
        setActiveTab('fitbit-integration')
        setLoadedTabs(prev => ({ ...prev, 'fitbit-integration': true }))
        setIsInitialized(true)
        return
      }

      // Проверяем URL только для глубоких табов
      const tabFromUrl = urlParams.get('tab')
      const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'purchase', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'profile', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']

      if (tabFromUrl && validTabs.includes(tabFromUrl) && deepTabs.includes(tabFromUrl) && window.history.length > 1) {
        // Восстанавливаем глубокий таб из URL только если есть история (не рестарт PWA)
        const params = {}
        urlParams.forEach((value, key) => {
          if (key !== 'tab') {
            try {
              params[key] = JSON.parse(value)
            } catch {
              params[key] = value
            }
          }
        })
        const deepTabUrl = window.location.pathname + window.location.search
        ensureBaseHistory(tabFromUrl, params, deepTabUrl)
        setActiveTab(tabFromUrl)
        setLoadedTabs(prev => ({ ...prev, [tabFromUrl]: true }))
        if (Object.keys(params).length > 0) {
          setTabParams(params)
          if (tabFromUrl === 'full' && params.selectedProject) {
            setSelectedProject(params.selectedProject)
          }
        }
      } else {
        // При рестарте PWA (history.length <= 1) с deep tab в URL — сбрасываем на current
        if (tabFromUrl && deepTabs.includes(tabFromUrl) && window.history.length <= 1) {
          window.history.replaceState({ tab: 'current' }, '', '/')
          setActiveTab('current')
          setLoadedTabs(prev => ({ ...prev, 'current': true }))
        } else {
          // Проверяем localStorage для основного таба
          const savedTab = window.localStorage?.getItem('activeTab')
          if (savedTab && validTabs.includes(savedTab) && mainTabs.includes(savedTab)) {
            setActiveTab(savedTab)
            setLoadedTabs(prev => ({ ...prev, [savedTab]: true }))
            // Сохраняем таб в history state для корректной работы кнопки "назад"
            window.history.replaceState({ tab: savedTab }, '', window.location.href)
          } else {
            // Если нет сохранённого таба — активируем current по умолчанию
            setLoadedTabs(prev => ({ ...prev, current: true }))
            window.history.replaceState({ tab: 'current' }, '', window.location.href)
          }
          // Очищаем URL от параметров таба, если это основной таб
          if (tabFromUrl && mainTabs.includes(tabFromUrl)) {
            const url = new URL(window.location)
            url.searchParams.delete('tab')
            url.searchParams.forEach((value, key) => {
              url.searchParams.delete(key)
            })
            window.history.replaceState({}, '', url)
          }
        }
      }
      setIsInitialized(true)
    } catch (err) {
      console.warn('Не удалось прочитать активный таб', err)
      setIsInitialized(true)
    }
  }, [isInitialized])

  const markTabAsLoaded = useCallback((tab) => {
    setLoadedTabs(prev => (prev[tab] ? prev : { ...prev, [tab]: true }))
  }, [])

  // Функция для обновления URL (только для глубоких табов)
  const updateUrl = useCallback((tab, params = {}, previousTab = null, replace = false) => {
    if (!deepTabs.includes(tab)) {
      // Для основных табов не обновляем URL
      return
    }
    
    const url = new URL(window.location)
    url.searchParams.set('tab', tab)
    
    // Удаляем старые параметры таба
    const keysToRemove = []
    url.searchParams.forEach((value, key) => {
      if (key !== 'tab') {
        keysToRemove.push(key)
      }
    })
    keysToRemove.forEach(key => url.searchParams.delete(key))
    
    // Добавляем новые параметры
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        url.searchParams.set(key, typeof value === 'object' ? JSON.stringify(value) : value)
      }
    })
    
    // Если стек пуст (после перезапуска PWA), добавляем базовую запись 'current'
    if (window.history.length <= 1) {
      window.history.replaceState({ tab: 'current' }, '', '/')
    }

    // Сохраняем предыдущий таб в state для восстановления при "Назад"
    if (replace) {
      window.history.replaceState({ tab, params, previousTab }, '', url)
    } else {
      window.history.pushState({ tab, params, previousTab }, '', url)
    }
  }, []) // deepTabs - константа, не нужно в зависимостях

  // Функция для очистки URL (при возврате к основному табу)
  const clearUrl = useCallback((tab = null, usePushState = false) => {
    const url = new URL(window.location)
    const hasTabParam = url.searchParams.has('tab')
    if (hasTabParam) {
      url.searchParams.delete('tab')
      url.searchParams.forEach((value, key) => {
        url.searchParams.delete(key)
      })
      // Сохраняем текущий таб в state для восстановления при "Назад"
      if (usePushState && tab) {
        window.history.pushState({ tab }, '', url)
      } else {
        window.history.replaceState(tab ? { tab } : {}, '', url)
      }
    } else if (tab) {
      // Если URL уже чистый, но нужно сохранить state таба
      if (usePushState) {
        window.history.pushState({ tab }, '', url)
      } else {
        window.history.replaceState({ tab }, '', url)
      }
    }
  }, [])

  // Функция для обновления URL без создания новой записи в истории (для обновления параметров того же таба)
  const replaceUrl = useCallback((tab, params = {}) => {
    if (!deepTabs.includes(tab)) {
      return
    }
    
    const url = new URL(window.location)
    url.searchParams.set('tab', tab)
    
    // Удаляем старые параметры таба
    const keysToRemove = []
    url.searchParams.forEach((value, key) => {
      if (key !== 'tab') {
        keysToRemove.push(key)
      }
    })
    keysToRemove.forEach(key => url.searchParams.delete(key))
    
    // Добавляем новые параметры
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        url.searchParams.set(key, typeof value === 'object' ? JSON.stringify(value) : value)
      }
    })
    
    // Сохраняем текущий state, чтобы не потерять previousTab
    const currentState = window.history.state || {}
    window.history.replaceState({ ...currentState, tab, params }, '', url)
  }, [])

  const fetchCurrentWeekData = useCallback(async (isBackground = false) => {
    try {
      if (isBackground) {
        setCurrentWeekBackgroundLoading(true)
      } else {
        setCurrentWeekLoading(true)
      }
      setCurrentWeekError(null)
      const response = await authFetch(CURRENT_WEEK_API_URL)
      if (!response.ok) {
        throw new Error('Ошибка загрузки данных')
      }
      const jsonData = await response.json()
      // Обрабатываем ответ: приходит массив с одним объектом [{total: ..., projects: [...]}]
      let projects = []
      let total = null
      let groupProgress1 = null
      let groupProgress2 = null
      let groupProgress0 = null
      
      if (Array.isArray(jsonData) && jsonData.length > 0) {
        // Если ответ - массив, проверяем первый элемент
        const firstItem = jsonData[0]
        if (firstItem && typeof firstItem === 'object') {
          // Если первый элемент - объект с полями total и projects
          if (firstItem.projects && Array.isArray(firstItem.projects)) {
            projects = firstItem.projects
            total = firstItem.total !== undefined ? firstItem.total : null
            groupProgress1 = firstItem.group_progress_1 !== undefined ? firstItem.group_progress_1 : null
            groupProgress2 = firstItem.group_progress_2 !== undefined ? firstItem.group_progress_2 : null
            groupProgress0 = firstItem.group_progress_0 !== undefined ? firstItem.group_progress_0 : null
          } else {
            // Если это просто массив проектов
            projects = jsonData
          }
        } else {
          // Если это массив проектов напрямую
          projects = jsonData
        }
      } else if (jsonData && typeof jsonData === 'object' && !Array.isArray(jsonData)) {
        // Если ответ - объект напрямую
        projects = jsonData.projects || jsonData.data || []
        total = jsonData.total !== undefined ? jsonData.total : null
        groupProgress1 = jsonData.group_progress_1 !== undefined ? jsonData.group_progress_1 : null
        groupProgress2 = jsonData.group_progress_2 !== undefined ? jsonData.group_progress_2 : null
        groupProgress0 = jsonData.group_progress_0 !== undefined ? jsonData.group_progress_0 : null
      }

      // Получаем желания и pending-баллы по проектам из ответа
      const wishes = jsonData?.wishes || []
      const pendingScoresByProject = jsonData?.pending_scores_by_project && typeof jsonData.pending_scores_by_project === 'object' ? jsonData.pending_scores_by_project : {}

      const rootData = (Array.isArray(jsonData) && jsonData.length > 0) ? jsonData[0] : jsonData
      const prioritiesConfirmedValue = rootData?.priorities_confirmed ?? null

      setCurrentWeekData({
        projects: Array.isArray(projects) ? projects : [],
        total: total,
        group_progress_1: groupProgress1,
        group_progress_2: groupProgress2,
        group_progress_0: groupProgress0,
        wishes: wishes,
        pending_scores_by_project: pendingScoresByProject
      })

      if (prioritiesConfirmedValue !== null) {
        setPrioritiesConfirmed(prioritiesConfirmedValue)
      }
    } catch (err) {
      setCurrentWeekError(err.message)
      console.error('Ошибка загрузки данных текущей недели:', err)
    } finally {
      if (isBackground) {
        setCurrentWeekBackgroundLoading(false)
      } else {
        setCurrentWeekLoading(false)
      }
    }
  }, [authFetch])

  const fetchFullStatisticsData = useCallback(async (isBackground = false) => {
    try {
      if (isBackground) {
        setFullStatisticsBackgroundLoading(true)
      } else {
        setFullStatisticsLoading(true)
      }
      setFullStatisticsError(null)
      const response = await authFetch(FULL_STATISTICS_API_URL)
      if (!response.ok) {
        throw new Error('Ошибка загрузки данных')
      }
      const jsonData = await response.json()
      setFullStatisticsData(jsonData)
    } catch (err) {
      setFullStatisticsError(err.message)
      console.error('Ошибка загрузки данных полной статистики:', err)
    } finally {
      if (isBackground) {
        setFullStatisticsBackgroundLoading(false)
      } else {
        setFullStatisticsLoading(false)
      }
    }
  }, [authFetch])
  
  const fetchTasksData = useCallback(async (isBackground = false) => {
    try {
      if (isBackground) {
        setTasksBackgroundLoading(true)
      } else {
        setTasksLoading(true)
      }
      setTasksError(null)
      const response = await authFetch('/api/tasks')
      if (!response.ok) {
        throw new Error('Ошибка загрузки данных')
      }
      const jsonData = await response.json()
      setTasksData(jsonData)
    } catch (err) {
      console.error('Ошибка загрузки списка задач:', err)
      setTasksError(err.message || 'Ошибка загрузки данных')
    } finally {
      if (isBackground) {
        setTasksBackgroundLoading(false)
      } else {
        setTasksLoading(false)
      }
    }
  }, [authFetch])

  const fetchTodayEntries = useCallback(async (isBackground = false, projectName = null, date = null) => {
    try {
      if (isBackground) {
        setTodayEntriesBackgroundLoading(true)
      } else {
        setTodayEntriesLoading(true)
      }
      setTodayEntriesError(null)
      
      // Формируем URL с опциональными параметрами project и date
      let url = '/api/today-entries'
      const params = []
      if (projectName) {
        params.push(`project=${encodeURIComponent(projectName)}`)
      }
      if (date) {
        params.push(`date=${encodeURIComponent(date)}`)
      }
      if (params.length > 0) {
        url += `?${params.join('&')}`
      }
      
      const response = await authFetch(url)
      if (!response.ok) {
        throw new Error('Ошибка загрузки данных')
      }
      const jsonData = await response.json()
      setTodayEntriesData(Array.isArray(jsonData) ? jsonData : [])
    } catch (err) {
      setTodayEntriesError(err.message || 'Ошибка загрузки данных')
      console.error('Ошибка загрузки today entries:', err)
    } finally {
      if (isBackground) {
        setTodayEntriesBackgroundLoading(false)
      } else {
        setTodayEntriesLoading(false)
      }
    }
  }, [authFetch])
  
  // Используем ref для отслеживания инициализации табов (чтобы избежать лишних пересозданий функции)
  const tabsInitializedRef = useRef({
    current: false,
    priorities: false,
    full: false,
    words: false,
    'add-words': false,
    dictionaries: false,
    test: false,
    tasks: false,
    'task-form': false,
    profile: false,
    'todoist-integration': false,
    'telegram-integration': false,
    'fitbit-integration': false,
    tracking: false,
    'tracking-access': false,
    'tracking-invite': false,
  })
  
  // Используем ref для отслеживания кеша (чтобы не зависеть от состояния в useCallback)
  const cacheRef = useRef({
    current: null,
    full: null,
    tasks: null,
    todayEntries: null,
  })
  
  // Refs для отслеживания активного таба
  const prevActiveTabRef = useRef(null)
  const lastLoadedTabRef = useRef(null) // Отслеживаем последний загруженный таб, чтобы избежать двойной загрузки
  
  // Обновляем ref при изменении данных
  useEffect(() => {
    cacheRef.current.current = currentWeekData
  }, [currentWeekData])
  
  useEffect(() => {
    cacheRef.current.full = fullStatisticsData
  }, [fullStatisticsData])
  
  useEffect(() => {
    cacheRef.current.tasks = tasksData
  }, [tasksData])

  useEffect(() => {
    cacheRef.current.todayEntries = todayEntriesData
  }, [todayEntriesData])
  
  // Функция для загрузки данных таба
  const loadTabData = useCallback((tab, isBackground = false, projectName = null) => {
    if (tab === 'current') {
      const hasCache = cacheRef.current.current !== null
      const isInitialized = tabsInitializedRef.current.current
      
      if (!isInitialized) {
        // Первая загрузка таба - загружаем с индикатором
        fetchCurrentWeekData(false)
        tabsInitializedRef.current.current = true
        setTabsInitialized(prev => ({ ...prev, current: true }))
      } else if (hasCache && isBackground) {
        // Возврат на таб с кешем - фоновая загрузка
        fetchCurrentWeekData(true)
      }
      // Если нет кеша и это не первая загрузка - ничего не делаем (данные уже загружаются)
    } else if (tab === 'full') {
      const hasCache = cacheRef.current.full !== null
      const hasCurrentWeekCache = cacheRef.current.current !== null
      const isInitialized = tabsInitializedRef.current.full
      
      if (!isInitialized) {
        // Первая загрузка таба
        if (hasCache) {
          // Если есть кеш - используем фоновую загрузку, показываем старые данные
          fetchFullStatisticsData(true)
        } else {
          // Если кеша нет - загружаем с индикатором
          fetchFullStatisticsData(false)
        }
        // Также запускаем фоновую загрузку currentWeekData, если его нет
        if (!hasCurrentWeekCache) {
          fetchCurrentWeekData(true)
        }
        // todayEntries будет загружен в FullStatistics компоненте при выборе дня
        tabsInitializedRef.current.full = true
        setTabsInitialized(prev => ({ ...prev, full: true }))
      } else if (hasCache && isBackground) {
        // Возврат на таб с кешем - фоновая загрузка
        fetchFullStatisticsData(true)
        // Также запускаем фоновую загрузку currentWeekData, если его нет
        if (!hasCurrentWeekCache) {
          fetchCurrentWeekData(true)
        }
        // todayEntries будет загружен в FullStatistics компоненте при выборе дня
      }
    } else if (tab === 'priorities') {
      const isInitialized = tabsInitializedRef.current.priorities
      
      if (!isInitialized) {
        // Первая загрузка таба
        setPrioritiesRefreshTrigger(prev => prev + 1)
        tabsInitializedRef.current.priorities = true
        setTabsInitialized(prev => ({ ...prev, priorities: true }))
      } else if (isBackground) {
        // Возврат на таб - фоновая загрузка
        setPrioritiesRefreshTrigger(prev => prev + 1)
      }
    } else if (tab === 'dictionaries') {
      const isInitialized = tabsInitializedRef.current['dictionaries']
      
      if (!isInitialized) {
        // Первая загрузка таба
        setDictionariesRefreshTrigger(prev => prev + 1)
        tabsInitializedRef.current['dictionaries'] = true
        setTabsInitialized(prev => ({ ...prev, 'dictionaries': true }))
      } else if (isBackground) {
        // Возврат на таб - фоновая загрузка
        setDictionariesRefreshTrigger(prev => prev + 1)
      }
    } else if (tab === 'tasks') {
      const hasCache = cacheRef.current.tasks !== null
      const isInitialized = tabsInitializedRef.current.tasks
      
      if (!isInitialized) {
        // Первая загрузка таба - загружаем с индикатором
        fetchTasksData(false)
        tabsInitializedRef.current.tasks = true
        setTabsInitialized(prev => ({ ...prev, tasks: true }))
      } else if (hasCache && isBackground) {
        // Возврат на таб с кешем - фоновая загрузка
        fetchTasksData(true)
      }
    }
  }, [fetchCurrentWeekData, fetchFullStatisticsData, fetchTasksData, fetchTodayEntries])

  // Функция для обновления всех данных (для кнопки Refresh, если она есть)
  const refreshAllData = useCallback(async () => {
    setIsRefreshing(true)
    setPrioritiesError(null)
    setCurrentWeekError(null)
    setFullStatisticsError(null)
    
    // Триггерим обновление приоритетов
    setPrioritiesRefreshTrigger(prev => prev + 1)
    
    // Загружаем все данные параллельно (не фоново)
    await Promise.all([
      fetchCurrentWeekData(false),
      fetchFullStatisticsData(false),
    ])
    
    setIsRefreshing(false)
  }, [fetchCurrentWeekData, fetchFullStatisticsData])
  
  // Обработчик кнопки "назад" в браузере (только для глубоких табов)
  useEffect(() => {
    const handlePopState = (event) => {
      // Проверяем, есть ли открытые модальные окна в DOM
      const taskDetailModal = document.querySelector('.task-detail-modal-overlay')
      const wishlistDetailModal = document.querySelector('.wishlist-detail-modal-overlay')
      const conditionFormOverlay = document.querySelector('.condition-form-overlay')

      // Если есть открытые модальные окна, не обрабатываем здесь - компоненты сами закроют их
      if (taskDetailModal || wishlistDetailModal || conditionFormOverlay) {
        return
      }

      // Если это модальное окно, не обрабатываем здесь - компоненты сами закроют его
      if (event.state && event.state.modalOpen) {
        // Если модальных окон нет в DOM, это устаревшая запись — пропускаем её
        if (!taskDetailModal && !wishlistDetailModal) {
          window.history.back()
        }
        return
      }

      const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'purchase', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'profile', 'todoist-integration', 'telegram-integration', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']

      // Проверяем state текущей записи истории (куда мы вернулись)
      if (event.state && event.state.tab) {
        const { tab, params = {} } = event.state
        
        if (validTabs.includes(tab)) {
          setActiveTab(tab)
          setTabParams(params)
          markTabAsLoaded(tab)
          // Если это экран full, устанавливаем selectedProject только если он есть в params
          if (tab === 'full') {
            setSelectedProject(params.selectedProject || null)
          }
          return
        }
      }
      
      // Если state пустой или не содержит таб, пытаемся восстановить из URL
      const urlParams = new URLSearchParams(window.location.search)
      const tabFromUrl = urlParams.get('tab')
      
      if (tabFromUrl && validTabs.includes(tabFromUrl) && deepTabs.includes(tabFromUrl)) {
        // Если в URL есть глубокий таб, восстанавливаем его
        setActiveTab(tabFromUrl)
        markTabAsLoaded(tabFromUrl)
        
        const params = {}
        urlParams.forEach((value, key) => {
          if (key !== 'tab') {
            try {
              params[key] = JSON.parse(value)
            } catch {
              params[key] = value
            }
          }
        })
        setTabParams(params)
        // Если это экран full, устанавливаем selectedProject только если он есть в params
        if (tabFromUrl === 'full') {
          setSelectedProject(params.selectedProject || null)
        }
      } else {
        // Если в URL нет глубокого таба, значит мы вернулись на основной таб
        // Проверяем state - если там есть tab, используем его
        if (event.state && event.state.tab && validTabs.includes(event.state.tab)) {
          setActiveTab(event.state.tab)
          setTabParams({})
          markTabAsLoaded(event.state.tab)
          setSelectedProject(null)
          clearUrl(event.state.tab)
        } else {
          // Если state пустой, используем сохраненный таб из localStorage (только основные табы)
          const savedTab = window.localStorage?.getItem('activeTab')
          const validMainTab = savedTab && mainTabs.includes(savedTab) ? savedTab : 'current'
          setActiveTab(validMainTab)
          setTabParams({})
          markTabAsLoaded(validMainTab)
          setSelectedProject(null)
          clearUrl(validMainTab)
        }
      }
    }
    
    window.addEventListener('popstate', handlePopState)
    
    return () => {
      window.removeEventListener('popstate', handlePopState)
    }
  }, [markTabAsLoaded, clearUrl]) // mainTabs и deepTabs - константы, не нужно в зависимостях

  // Обновляем данные при возвращении экрана в фокус (фоново)
  useEffect(() => {
    const handleFocus = () => {
      if (document.visibilityState === 'visible') {
        // Загружаем данные активного таба фоново
        const projectName = activeTab === 'full' ? selectedProject : null
        loadTabData(activeTab, true, projectName)
      }
    }
    
    window.addEventListener('focus', handleFocus)
    document.addEventListener('visibilitychange', handleFocus)
    
    return () => {
      window.removeEventListener('focus', handleFocus)
      document.removeEventListener('visibilitychange', handleFocus)
    }
  }, [activeTab, loadTabData])

  const handleProjectClick = (projectName) => {
    setSelectedProject(projectName)
    markTabAsLoaded('full')
    setTabParams({ selectedProject: projectName })
    updateUrl('full', { selectedProject: projectName }, activeTab)
    setActiveTab('full')
  }

  const handleTabChange = (tab, params = {}, options = {}) => {
    if (tab === 'full' && activeTab === 'full') {
      // При повторном клике на "Полная статистика" сбрасываем выбранный проект
      setSelectedProject(null)
      setTabParams({})
      updateUrl('full', {}, activeTab)
    } else if (tab !== activeTab || tab === 'task-form' || tab === 'wishlist-form' || tab === 'shopping-item-form' || (tab === 'words' && Object.keys(params).length > 0)) {
      // Для task-form, wishlist-form и shopping-item-form всегда обновляем параметры, даже если это тот же таб
      markTabAsLoaded(tab)

      // Определяем, является ли текущий таб глубоким
      const isCurrentTabDeep = deepTabs.includes(activeTab)
      const isNewTabDeep = deepTabs.includes(tab)
      const isCurrentTabMain = mainTabs.includes(activeTab)
      const isNewTabMain = mainTabs.includes(tab)

      {
        // Для task-form и wishlist-form явно удаляем параметры, только если нет никаких параметров
        // task-form может иметь taskId (редактирование), wishlistId (создание из желания), returnTo (возврат после создания)
        const isTaskFormWithNoParams = tab === 'task-form' && params.taskId === undefined && params.wishlistId === undefined && params.returnTo === undefined
        // Проверяем, что boardId не null и не undefined (null означает "нет доски", но это валидное значение)
        const hasBoardId = params.boardId !== null && params.boardId !== undefined
        const isWishlistFormWithNoParams = tab === 'wishlist-form' && params.wishlistId === undefined && params.newTaskId === undefined && !hasBoardId
        if (isTaskFormWithNoParams || isWishlistFormWithNoParams) {
          setTabParams({})
          if (isNewTabMain) {
            clearUrl()
          } else if (isNewTabDeep) {
            // Если текущая запись — модальное окно, заменяем её вместо push
            const currentState = window.history.state || {}
            const isFromModal = currentState.modalOpen === true || currentState.conditionForm === true
            if (isFromModal) {
              const url = new URL(window.location)
              url.searchParams.set('tab', tab)
              const keysToRemove = []
              url.searchParams.forEach((value, key) => { if (key !== 'tab') keysToRemove.push(key) })
              keysToRemove.forEach(key => url.searchParams.delete(key))
              window.history.replaceState({ tab, params: {}, previousTab: activeTab }, '', url)
            } else {
              updateUrl(tab, {}, activeTab)
            }
          }
        } else {
          setTabParams(params)
          // Обновляем URL только для глубоких табов
          if (isNewTabDeep) {
            // Проверяем, была ли последняя запись в истории от модального окна
            const currentState = window.history.state || {}
            const isFromModal = currentState.modalOpen === true || currentState.conditionForm === true
            const isNavigatingToForm = tab === 'task-form' || tab === 'wishlist-form' || tab === 'shopping-item-form'
            
            if (isFromModal && isNavigatingToForm) {
              // Заменяем запись модального окна на запись формы редактирования
              // Используем replaceState вместо pushState, сохраняя activeTab как previousTab
              const url = new URL(window.location)
              url.searchParams.set('tab', tab)
              // Удаляем старые параметры
              const keysToRemove = []
              url.searchParams.forEach((value, key) => {
                if (key !== 'tab') keysToRemove.push(key)
              })
              keysToRemove.forEach(key => url.searchParams.delete(key))
              // Добавляем новые параметры
              Object.entries(params).forEach(([key, value]) => {
                if (value !== undefined && value !== null) {
                  url.searchParams.set(key, typeof value === 'object' ? JSON.stringify(value) : value)
                }
              })
              window.history.replaceState({ tab, params, previousTab: activeTab }, '', url)
            } else {
              // Сохраняем текущий таб как предыдущий при переходе на глубокий таб
              updateUrl(tab, params, activeTab, options.replace)
            }
          } else if (isNewTabMain && isCurrentTabDeep) {
            // При переходе с глубокого таба на основной - очищаем URL и сохраняем таб в state
            clearUrl(tab)
          } else if (isNewTabMain && isCurrentTabMain) {
            // При переходе между основными табами - сохраняем таб в state без изменения URL, НЕ создаем новую запись в истории
            clearUrl(tab, false)
          }
        }
      }

      setActiveTab(tab)
      if (tab === 'current') {
        setSelectedProject(null)
      } else if (tab === 'full') {
        // Если переходим на full без selectedProject в params, очищаем выбранный проект
        if (!params.selectedProject) {
          setSelectedProject(null)
        }
      }
      // Обновляем список слов при возврате из экрана добавления слов
      if (activeTab === 'add-words' && tab === 'words') {
        setWordsRefreshTrigger(prev => prev + 1)
      }
      // Обновляем список задач при возврате из экрана редактирования или теста
      // Используем фоновую загрузку, чтобы не показывать индикатор загрузки
      if ((activeTab === 'task-form' || activeTab === 'test' || activeTab === 'purchase') && tab === 'tasks') {
        fetchTasksData(true)
      }
      // Сохраняем предыдущий таб при открытии wishlist-form или wishlist-detail
      if ((tab === 'wishlist-form' || tab === 'wishlist-detail') && activeTab !== tab) {
        setPreviousTab(activeTab)
      }

      // Обновляем список желаний при возврате из экрана редактирования
      if (activeTab === 'wishlist-form' && tab !== 'wishlist-form') {
        // Сохраняем boardId из параметров или текущих tabParams
        const savedBoardId = params.boardId || tabParams.boardId
        // Параметры уже установлены в строке 649, но мы можем их обновить, чтобы сохранить boardId
        if (savedBoardId && tab === 'wishlist') {
          setTabParams(prev => ({ ...prev, boardId: savedBoardId }))
        }
        if (tab === 'wishlist') {
          setWishlistRefreshTrigger(prev => prev + 1)
        }
      }

      // Обновляем список желаний при возврате из экрана детализации
      if (activeTab === 'wishlist-detail' && tab !== 'wishlist-detail') {
        if (tab === 'wishlist') {
          setWishlistRefreshTrigger(prev => prev + 1)
        }
      }

      // Сохраняем предыдущий таб при открытии shopping-item-form
      if (tab === 'shopping-item-form' && activeTab !== tab) {
        setPreviousTab(activeTab)
        setShoppingItemFormKey(prev => prev + 1)
      }

      // Обновляем список товаров при возврате из экрана редактирования
      if ((activeTab === 'shopping-item-form' || activeTab === 'shopping-board-form') && (tab === 'shopping' || tab === 'purchase')) {
        const savedBoardId = params.boardId || tabParams.boardId
        if (savedBoardId) {
          setTabParams(prev => ({ ...prev, boardId: savedBoardId }))
        }
        setShoppingRefreshTrigger(prev => prev + 1)
      }
      // Загрузка данных произойдет в useEffect при изменении activeTab
    }
  }

  // Обработчик для кнопки добавления задачи
  const handleAddClick = () => {
    handleNavigate('task-form', { taskId: undefined })
  }

  // Обработчик навигации для компонентов
  const handleNavigate = (tab, params = {}, options = {}) => {
    handleTabChange(tab, params, options)
  }

  // Загружаем данные при открытии таба (когда таб становится активным)
  useEffect(() => {
    if (!activeTab || !loadedTabs[activeTab]) return

    const isFirstLoad = !tabsInitializedRef.current[activeTab]
    const isReturningToTab = prevActiveTabRef.current !== null && prevActiveTabRef.current !== activeTab

    // Проверяем, не загружали ли мы уже этот таб в этом рендере
    const tabKey = `${activeTab}-${isFirstLoad ? 'first' : 'return'}`
    if (lastLoadedTabRef.current === tabKey) {
      return // Уже загружали
    }

    // Обновляем список слов при возврате из экрана добавления слов
    if (prevActiveTabRef.current === 'add-words' && activeTab === 'words') {
      setWordsRefreshTrigger(prev => prev + 1)
    }

    // Обновляем список желаний при возврате из формы редактирования
    if (prevActiveTabRef.current === 'wishlist-form' && activeTab === 'wishlist') {
      setWishlistRefreshTrigger(prev => prev + 1)
    }

    if (isFirstLoad) {
      // Первая загрузка таба
      lastLoadedTabRef.current = tabKey
      const projectName = activeTab === 'full' ? selectedProject : null
      loadTabData(activeTab, false, projectName)
    } else if (isReturningToTab) {
      // Возврат на таб - фоновая загрузка
      lastLoadedTabRef.current = tabKey
      const projectName = activeTab === 'full' ? selectedProject : null
      loadTabData(activeTab, true, projectName)
    }

    prevActiveTabRef.current = activeTab
  }, [activeTab, loadedTabs, loadTabData, selectedProject])

  // Обновляем todayEntries при изменении selectedProject для таба 'full'
  // НЕ загружаем данные при открытии таба - это делает компонент FullStatistics
  // Загружаем только при изменении selectedProject, если таб уже открыт
  useEffect(() => {
    if (activeTab === 'full' && prevActiveTabRef.current === 'full') {
      // Таб уже был открыт, просто изменился selectedProject
      // Данные будут загружены компонентом FullStatistics с правильной датой
    }
  }, [selectedProject, activeTab])


  
  // Определяем общее состояние загрузки и ошибок для кнопки Refresh
  const isAnyLoading = currentWeekLoading || fullStatisticsLoading || prioritiesLoading || isRefreshing
  const hasAnyError = currentWeekError || fullStatisticsError || prioritiesError

  // Сохраняем выбранный таб, чтобы восстановить его после перезагрузки
  useEffect(() => {
    try {
      window.localStorage?.setItem('activeTab', activeTab)
    } catch (err) {
      console.warn('Не удалось сохранить активный таб в localStorage', err)
    }
  }, [activeTab])

  // Show loading while checking auth
  if (authLoading) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900">
        <div className="text-white text-xl">Загрузка...</div>
      </div>
    )
  }
  
  // Show auth screen if not authenticated
  if (!isAuthenticated) {
    prevIsAuthenticatedRef.current = false
    return <AuthScreen />
  }

  // Определяем, нужно ли скрывать нижнюю панель (для fullscreen экранов)
  const isFullscreenTab = activeTab === 'test' || activeTab === 'purchase' || activeTab === 'add-words' || activeTab === 'task-form' || activeTab === 'wishlist-form' || activeTab === 'wishlist-detail' || activeTab === 'todoist-integration' || activeTab === 'telegram-integration' || activeTab === 'fitbit-integration' || activeTab === 'full' || activeTab === 'priorities' || activeTab === 'words' || activeTab === 'dictionaries' || activeTab === 'tracking' || activeTab === 'tracking-access' || activeTab === 'tracking-invite' || activeTab === 'shopping' || activeTab === 'shopping-item-form' || activeTab === 'shopping-board-form' || activeTab === 'shopping-board-join' || activeTab === 'shopping-item-history'
  
  // Функция для получения классов скролл-контейнера для каждого таба
  // Каждый таб имеет свой изолированный скролл-контейнер для автоматического сохранения позиции скролла
  const getTabContainerClasses = (tabName) => {
    const isActive = activeTab === tabName
    const baseClasses = 'absolute inset-0 overflow-y-auto'
    // Активный таб: z-10 (сверху), неактивные: z-0 + invisible + opacity-0 (мгновенное скрытие)
    const visibilityClasses = isActive ? 'z-10' : 'z-0 invisible opacity-0 pointer-events-none'
    
    // Определяем padding для каждого таба
    let paddingClasses = ''
    if (tabName === 'current' || tabName === 'tasks' || tabName === 'wishlist' || tabName === 'profile') {
      paddingClasses = 'pb-20'
    } else if (tabName === 'priorities') {
      paddingClasses = 'pb-20'
    } else if (tabName === 'words' || tabName === 'dictionaries' || tabName === 'shopping') {
      paddingClasses = 'pb-16'
    }
    
    return `${baseClasses} ${paddingClasses} ${visibilityClasses}`.trim()
  }
  
  // Функция для определения отступов внутреннего контейнера
  const getInnerContainerClasses = (tabName) => {
    if (tabName === 'tasks' || tabName === 'wishlist' || tabName === 'profile') {
      return 'max-w-7xl mx-auto p-4 md:p-8'
    }
    if (tabName === 'current') {
      return 'max-w-7xl mx-auto p-4 md:p-6'
    }
    if (tabName === 'full' || tabName === 'priorities' || tabName === 'dictionaries' || tabName === 'words' || tabName === 'shopping' || tabName === 'shopping-item-history' || tabName === 'purchase') {
      return 'max-w-7xl mx-auto px-4 md:px-8 py-0'
    }
    // Fullscreen табы без отступов
    return 'max-w-7xl mx-auto p-0'
  }

  return (
    <div className="flex flex-col h-screen h-dvh overflow-hidden">
      {/* Контейнер табов - каждый таб имеет свой изолированный скролл */}
      <div className="flex-1 relative overflow-hidden">
        {loadedTabs.current && (
          <div className={getTabContainerClasses('current')}>
            <div className={getInnerContainerClasses('current')}>
              <CurrentWeek 
                onProjectClick={handleProjectClick}
                data={currentWeekData}
                loading={currentWeekLoading}
                error={currentWeekError}
                onRetry={fetchCurrentWeekData}
                allProjectsData={fullStatisticsData}
                onNavigate={handleNavigate}
                onOpenAddModal={(setOpenFn) => {
                  currentWeekAddModalRef.current = setOpenFn
                }}
              />
            </div>
          </div>
        )}

        {loadedTabs.priorities && (
          <div className={getTabContainerClasses('priorities')}>
            <div className={getInnerContainerClasses('priorities')}>
              <ProjectPriorityManager
                allProjectsData={fullStatisticsData}
                currentWeekData={currentWeekData}
                shouldLoad={activeTab === 'priorities' && loadedTabs.priorities}
                onLoadingChange={setPrioritiesLoading}
                onErrorChange={setPrioritiesError}
                refreshTrigger={prioritiesRefreshTrigger}
                onNavigate={handleNavigate}
                onConfirmed={async () => {
                  await fetchCurrentWeekData(false)
                  setPrioritiesConfirmed(true)
                  markTabAsLoaded('current')
                  setActiveTab('current')
                }}
              />
            </div>
          </div>
        )}

        {loadedTabs.full && (
          <div className={getTabContainerClasses('full')}>
            <div className={getInnerContainerClasses('full')}>
              <FullStatistics 
                selectedProject={selectedProject} 
                onClearSelection={() => {
                  setSelectedProject(null)
                  setTabParams({})
                  replaceUrl('full', {})
                }}
                data={fullStatisticsData}
                loading={fullStatisticsLoading}
                error={fullStatisticsError}
                todayEntries={todayEntriesData}
                todayEntriesLoading={todayEntriesLoading || todayEntriesBackgroundLoading}
                todayEntriesError={todayEntriesError}
                onRetryTodayEntries={() => fetchTodayEntries(false, selectedProject, null)}
                fetchTodayEntries={fetchTodayEntries}
                onRetry={fetchFullStatisticsData}
                currentWeekData={currentWeekData}
                fetchCurrentWeekData={fetchCurrentWeekData}
                onNavigate={handleNavigate}
                activeTab={activeTab}
              />
            </div>
          </div>
        )}

        {loadedTabs.words && (
          <div className={getTabContainerClasses('words')}>
            <div className={getInnerContainerClasses('words')}>
              <WordList 
                onNavigate={handleNavigate}
                dictionaryId={tabParams.dictionaryId}
                isNewDictionary={tabParams.isNewDictionary}
                refreshTrigger={wordsRefreshTrigger}
              />
            </div>
          </div>
        )}

        {loadedTabs['add-words'] && (
          <div className={getTabContainerClasses('add-words')}>
            <div className={getInnerContainerClasses('add-words')}>
              <AddWords 
                onNavigate={handleNavigate}
                dictionaryId={tabParams.dictionaryId}
                dictionaryName={tabParams.dictionaryName}
              />
            </div>
          </div>
        )}

        {loadedTabs.dictionaries && (
          <div className={getTabContainerClasses('dictionaries')}>
            <div className={getInnerContainerClasses('dictionaries')}>
              <DictionaryList 
                onNavigate={handleNavigate}
                refreshTrigger={dictionariesRefreshTrigger}
              />
            </div>
          </div>
        )}

        {loadedTabs.test && (
          <div className={getTabContainerClasses('test')}>
            <div className={getInnerContainerClasses('test')}>
              <TestWords
                onNavigate={handleNavigate}
                wordCount={tabParams.wordCount}
                configId={tabParams.configId}
                maxCards={tabParams.maxCards}
                taskId={tabParams.taskId}
              />
            </div>
          </div>
        )}

        {loadedTabs.purchase && (
          <div className={getTabContainerClasses('purchase')}>
            <div className={getInnerContainerClasses('purchase')}>
              <PurchaseScreen
                onNavigate={handleNavigate}
                purchaseConfigId={tabParams.purchaseConfigId}
                taskId={tabParams.taskId}
                taskName={tabParams.taskName}
              />
            </div>
          </div>
        )}

        {loadedTabs.tasks && (
          <div className={getTabContainerClasses('tasks')}>
            <div className={getInnerContainerClasses('tasks')}>
              <TaskList 
                onNavigate={handleNavigate}
                data={tasksData}
                loading={tasksLoading}
                backgroundLoading={tasksBackgroundLoading}
                error={tasksError}
                onRetry={() => fetchTasksData(false)}
                onRefresh={(tasksOrBackground) => {
                  if (Array.isArray(tasksOrBackground)) {
                    setTasksData(tasksOrBackground)
                  } else {
                    fetchTasksData(tasksOrBackground === true)
                  }
                }}
              />
            </div>
          </div>
        )}

        {loadedTabs['task-form'] && (
          <div className={getTabContainerClasses('task-form')}>
            <div className={getInnerContainerClasses('task-form')}>
              <TaskForm
                key={tabParams.taskId || 'new-task'}
                onNavigate={handleNavigate}
                taskId={tabParams.taskId}
                wishlistId={tabParams.wishlistId}
                returnTo={tabParams.returnTo}
                returnWishlistId={tabParams.returnWishlistId}
              />
            </div>
          </div>
        )}

        {loadedTabs.wishlist && (
          <div className={getTabContainerClasses('wishlist')}>
            <div className={getInnerContainerClasses('wishlist')}>
              <Wishlist 
                onNavigate={handleNavigate}
                refreshTrigger={wishlistRefreshTrigger}
                isActive={activeTab === 'wishlist'}
                initialBoardId={tabParams.boardId}
                boardDeleted={tabParams.boardDeleted}
              />
            </div>
          </div>
        )}

        {loadedTabs['wishlist-form'] && (
          <div className={getTabContainerClasses('wishlist-form')}>
            <div className={getInnerContainerClasses('wishlist-form')}>
              <WishlistForm
                key={`${tabParams.wishlistId || 'new'}-${tabParams.editConditionIndex ?? ''}-${tabParams.newTaskId ?? ''}-${tabParams.boardId ?? ''}`}
                onNavigate={handleNavigate}
                wishlistId={tabParams.wishlistId}
                editConditionIndex={tabParams.editConditionIndex}
                newTaskId={tabParams.newTaskId}
                boardId={tabParams.boardId}
              />
            </div>
          </div>
        )}

        {loadedTabs['board-form'] && (
          <div className={getTabContainerClasses('board-form')}>
            <div className={getInnerContainerClasses('board-form')}>
              <BoardForm
                key={tabParams.boardId || 'new'}
                onNavigate={handleNavigate}
                boardId={tabParams.boardId}
                onSaved={() => setWishlistRefreshTrigger(prev => prev + 1)}
              />
            </div>
          </div>
        )}

        {loadedTabs['board-join'] && (
          <div className={getTabContainerClasses('board-join')}>
            <div className={getInnerContainerClasses('board-join')}>
              <BoardJoinPreview
                key={tabParams.inviteToken}
                onNavigate={handleNavigate}
                inviteToken={tabParams.inviteToken}
              />
            </div>
          </div>
        )}

        {loadedTabs.shopping && (
          <div className={getTabContainerClasses('shopping')}>
            <div className={getInnerContainerClasses('shopping')}>
              <ShoppingList
                onNavigate={handleNavigate}
                refreshTrigger={shoppingRefreshTrigger}
                isActive={activeTab === 'shopping'}
                initialBoardId={tabParams.boardId}
                boardDeleted={tabParams.boardDeleted}
              />
            </div>
          </div>
        )}

        {loadedTabs['shopping-item-form'] && (
          <div className={getTabContainerClasses('shopping-item-form')}>
            <div className={getInnerContainerClasses('shopping-item-form')}>
              <ShoppingItemForm
                key={tabParams.itemId || `new-${shoppingItemFormKey}`}
                onNavigate={handleNavigate}
                itemId={tabParams.itemId}
                boardId={tabParams.boardId}
                previousTab={previousTab}
                onSaved={() => setShoppingRefreshTrigger(prev => prev + 1)}
              />
            </div>
          </div>
        )}

        {loadedTabs['shopping-board-form'] && (
          <div className={getTabContainerClasses('shopping-board-form')}>
            <div className={getInnerContainerClasses('shopping-board-form')}>
              <ShoppingBoardForm
                key={tabParams.boardId || 'new'}
                onNavigate={handleNavigate}
                boardId={tabParams.boardId}
                onSaved={() => setShoppingRefreshTrigger(prev => prev + 1)}
              />
            </div>
          </div>
        )}

        {loadedTabs['shopping-board-join'] && (
          <div className={getTabContainerClasses('shopping-board-join')}>
            <div className={getInnerContainerClasses('shopping-board-join')}>
              <ShoppingBoardJoinPreview
                key={tabParams.inviteToken}
                onNavigate={handleNavigate}
                inviteToken={tabParams.inviteToken}
              />
            </div>
          </div>
        )}

        {loadedTabs['shopping-item-history'] && (
          <div className={getTabContainerClasses('shopping-item-history')}>
            <div className={getInnerContainerClasses('shopping-item-history')}>
              <ShoppingItemHistory
                key={tabParams.itemId}
                itemId={tabParams.itemId}
                onNavigate={handleNavigate}
              />
            </div>
          </div>
        )}

        {loadedTabs.profile && (
          <div className={getTabContainerClasses('profile')}>
            <div className={getInnerContainerClasses('profile')}>
              <Profile onNavigate={handleNavigate} />
            </div>
          </div>
        )}

        {loadedTabs['todoist-integration'] && (
          <div className={getTabContainerClasses('todoist-integration')}>
            <div className={getInnerContainerClasses('todoist-integration')}>
              <TodoistIntegration onNavigate={handleNavigate} />
            </div>
          </div>
        )}

        {loadedTabs['telegram-integration'] && (
          <div className={getTabContainerClasses('telegram-integration')}>
            <div className={getInnerContainerClasses('telegram-integration')}>
              <TelegramIntegration onNavigate={handleNavigate} />
            </div>
          </div>
        )}

        {loadedTabs['fitbit-integration'] && (
          <div className={getTabContainerClasses('fitbit-integration')}>
            <div className={getInnerContainerClasses('fitbit-integration')}>
              <FitbitIntegration onNavigate={handleNavigate} />
            </div>
          </div>
        )}

        {loadedTabs.tracking && (
          <div className={getTabContainerClasses('tracking')}>
            <div className={getInnerContainerClasses('tracking')}>
              <Tracking 
                onNavigate={handleNavigate} 
                activeTab={activeTab}
              />
            </div>
          </div>
        )}

        {loadedTabs['tracking-access'] && (
          <div className={getTabContainerClasses('tracking-access')}>
            <div className={getInnerContainerClasses('tracking-access')}>
              <TrackingAccess onNavigate={handleNavigate} activeTab={activeTab} />
            </div>
          </div>
        )}

        {loadedTabs['tracking-invite'] && (
          <div className={getTabContainerClasses('tracking-invite')}>
            <div className={getInnerContainerClasses('tracking-invite')}>
              <TrackingInviteAccept 
                inviteToken={tabParams.inviteToken}
                onNavigate={handleNavigate} 
              />
            </div>
          </div>
        )}
      </div>

      {/* Кнопка добавления задачи (только для таба задач) */}
      {!isFullscreenTab && activeTab === 'tasks' && (
        <button
          onClick={handleAddClick}
          className="fixed bottom-16 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
          title="Добавить задачу"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M12 5v14M5 12h14" />
          </svg>
        </button>
      )}

      {/* Кнопка добавления желания (только для таба wishlist) */}
      {!isFullscreenTab && activeTab === 'wishlist' && (
        <button
          onClick={() => {
            // Получаем boardId из tabParams или из localStorage (где его сохраняет компонент Wishlist)
            let boardId = tabParams.boardId
            if (!boardId) {
              try {
                const saved = localStorage.getItem('wishlist_selected_board_id')
                if (saved) {
                  const parsed = parseInt(saved, 10)
                  if (!isNaN(parsed)) boardId = parsed
                }
              } catch (err) {
                console.error('Error loading boardId from localStorage:', err)
              }
            }
            handleNavigate('wishlist-form', { wishlistId: undefined, boardId: boardId })
          }}
          className="fixed bottom-16 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
          title="Добавить желание"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M12 5v14M5 12h14" />
          </svg>
        </button>
      )}

      {/* Кнопка добавления товара (только для таба shopping) */}
      {activeTab === 'shopping' && (
        <button
          onClick={() => {
            let boardId = tabParams.boardId
            if (!boardId) {
              try {
                const saved = localStorage.getItem('shopping_selected_board_id')
                if (saved) {
                  const parsed = parseInt(saved, 10)
                  if (!isNaN(parsed)) boardId = parsed
                }
              } catch (err) {
                console.error('Error loading boardId from localStorage:', err)
              }
            }
            handleNavigate('shopping-item-form', { itemId: undefined, boardId: boardId })
          }}
          className="fixed bottom-4 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
          title="Добавить товар"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M12 5v14M5 12h14" />
          </svg>
        </button>
      )}

      {/* Кнопка добавления записи (только для таба current - экран прогресса) */}
      {!isFullscreenTab && activeTab === 'current' && (
        <button
          onClick={() => {
            if (currentWeekAddModalRef.current) {
              currentWeekAddModalRef.current()
            }
          }}
          className="fixed bottom-16 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
          title="Добавить запись"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M12 5v14M5 12h14" />
          </svg>
        </button>
      )}

      {/* Кнопка добавления словаря (только для таба dictionaries) */}
      {activeTab === 'dictionaries' && (
        <button
          onClick={() => handleNavigate('words', { dictionaryId: null, isNewDictionary: true })}
          className="fixed bottom-4 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
          title="Добавить словарь"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M12 5v14M5 12h14" />
          </svg>
        </button>
      )}

      {/* Кнопка добавления слов (только для таба words) */}
      {activeTab === 'words' && (
        <button
          onClick={() => {
            handleNavigate('add-words', { dictionaryId: tabParams.dictionaryId, dictionaryName: tabParams.dictionaryName })
          }}
          className="fixed bottom-4 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
          title="Добавить слова"
        >
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
            strokeLinecap="round"
            strokeLinejoin="round"
          >
            <path d="M12 5v14M5 12h14" />
          </svg>
        </button>
      )}

      {!isFullscreenTab && (
        <div className="fixed bottom-0 left-0 right-0 flex bg-white/90 backdrop-blur-md border-t border-white/20 flex-shrink-0 overflow-x-auto shadow-lg z-10 justify-center items-center w-full" style={{ paddingBottom: 'env(safe-area-inset-bottom)' }}>
          <div className="flex">
            <button
              onClick={() => handleTabChange('current')}
              className={`min-w-max whitespace-nowrap px-4 py-4 transition-all duration-300 relative ${
                activeTab === 'current'
                  ? 'text-indigo-700 bg-white/50'
                  : 'text-gray-600 hover:text-indigo-600 hover:bg-white/30'
              }`}
              title="Неделя"
            >
              <span className="relative z-10 flex items-center justify-center">
                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
                  <line x1="16" y1="2" x2="16" y2="6"></line>
                  <line x1="8" y1="2" x2="8" y2="6"></line>
                  <line x1="3" y1="10" x2="21" y2="10"></line>
                </svg>
              </span>
              {activeTab === 'current' && (
                <div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-indigo-500 to-purple-500"></div>
              )}
            </button>
            <button
              onClick={() => handleTabChange('tasks')}
              className={`min-w-max whitespace-nowrap px-4 py-4 transition-all duration-300 relative ${
                activeTab === 'tasks' || activeTab === 'task-form'
                  ? 'text-indigo-700 bg-white/50'
                  : 'text-gray-600 hover:text-indigo-600 hover:bg-white/30'
              }`}
              title="Задачи"
            >
              <span className="relative z-10 flex items-center justify-center">
                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M9 11l3 3L22 4"></path>
                  <path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
                </svg>
              </span>
              {(activeTab === 'tasks' || activeTab === 'task-form') && (
                <div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-indigo-500 to-purple-500"></div>
              )}
            </button>
            <button
              onClick={() => handleTabChange('wishlist')}
              className={`min-w-max whitespace-nowrap px-4 py-4 transition-all duration-300 relative ${
                activeTab === 'wishlist' || activeTab === 'wishlist-form'
                  ? 'text-indigo-700 bg-white/50'
                  : 'text-gray-600 hover:text-indigo-600 hover:bg-white/30'
              }`}
              title="Желания"
            >
              <span className="relative z-10 flex items-center justify-center">
                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <polyline points="20 12 20 22 4 22 4 12"></polyline>
                  <rect x="2" y="7" width="20" height="5"></rect>
                  <line x1="12" y1="22" x2="12" y2="7"></line>
                  <path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"></path>
                  <path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"></path>
                </svg>
              </span>
              {(activeTab === 'wishlist' || activeTab === 'wishlist-form') && (
                <div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-indigo-500 to-purple-500"></div>
              )}
            </button>
            <button
              onClick={() => handleTabChange('profile')}
              className={`min-w-max whitespace-nowrap px-4 py-4 transition-all duration-300 relative ${
                activeTab === 'profile'
                  ? 'text-indigo-700 bg-white/50'
                  : 'text-gray-600 hover:text-indigo-600 hover:bg-white/30'
              }`}
              title="Профиль"
            >
              <span className="relative z-10 flex items-center justify-center">
                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
                  <circle cx="12" cy="7" r="4"></circle>
                </svg>
              </span>
              {activeTab === 'profile' && (
                <div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-indigo-500 to-purple-500"></div>
              )}
            </button>
          </div>
        </div>
      )}

      {/* Оверлей подтверждения приоритетов — показывается поверх экрана прогресса недели */}
      {activeTab === 'current' && prioritiesConfirmed === false && (
        <div className="fixed inset-0 bg-white z-50 overflow-y-auto">
          <div className="max-w-2xl mx-auto px-4 h-full">
            <ProjectPriorityManager
              allProjectsData={fullStatisticsData}
              currentWeekData={currentWeekData}
              shouldLoad={true}
              onLoadingChange={setPrioritiesLoading}
              onErrorChange={setPrioritiesError}
              refreshTrigger={Math.max(prioritiesRefreshTrigger, 1)}
              onNavigate={handleNavigate}
              onConfirmed={async () => {
                await fetchCurrentWeekData(false)
                setPrioritiesConfirmed(true)
              }}
              onClose={() => {
                // history.back() переходит к { tab: 'tasks' }, popstate обработает переключение
                window.history.back()
              }}
            />
          </div>
        </div>
      )}

    </div>
  )
}

function App() {
  return (
    <AuthProvider>
      <AppContent />
      <PWAUpdatePrompt />
    </AuthProvider>
  )
}

export default App


