import React, { useState, useEffect, useRef, useMemo } from 'react'
import { createPortal } from 'react-dom'
import { useAuth } from './auth/AuthContext'
import BoardSelector from './BoardSelector'
import ShoppingItemDetail from './ShoppingItemDetail'
import LoadingError from './LoadingError'
import Toast from './Toast'
import { DayPicker } from 'react-day-picker'
import { ru } from 'react-day-picker/locale'
import 'react-day-picker/style.css'
import './TaskList.css'
import './ShoppingList.css'

const BOARDS_CACHE_KEY = 'shopping_boards_cache'
const ITEMS_CACHE_KEY = 'shopping_items_cache'
const SELECTED_BOARD_KEY = 'shopping_selected_board_id'

// Форматирование даты в YYYY-MM-DD (локальное время)
const formatDateToLocal = (date) => {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}

// Форматирование даты для отображения
const formatDateForDisplay = (dateStr) => {
  if (!dateStr) return ''
  const date = new Date(dateStr)
  if (isNaN(date.getTime())) return ''

  const now = new Date()
  now.setHours(0, 0, 0, 0)
  const target = new Date(date.getFullYear(), date.getMonth(), date.getDate())

  const diffDays = Math.floor((target - now) / (1000 * 60 * 60 * 24))

  if (diffDays === 0) return 'Сегодня'
  if (diffDays === 1) return 'Завтра'
  if (diffDays === -1) return 'Вчера'

  if (diffDays > 0 && diffDays <= 7) {
    const dayNames = ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота']
    return dayNames[target.getDay()]
  }

  const monthNames = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
    'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']

  if (target.getFullYear() === now.getFullYear()) {
    return `${target.getDate()} ${monthNames[target.getMonth()]}`
  }
  return `${target.getDate()} ${monthNames[target.getMonth()]} ${target.getFullYear()}`
}

// Вычисление следующей даты по repetition_period
const calculateNextDateFromRepetitionPeriod = (repetitionPeriodStr) => {
  if (!repetitionPeriodStr) return null
  const parts = repetitionPeriodStr.trim().split(/\s+/)
  if (parts.length < 2) return null
  const value = parseInt(parts[0], 10)
  if (isNaN(value) || value === 0) return null
  const unit = parts[1].toLowerCase()
  const now = new Date()
  now.setHours(0, 0, 0, 0)
  const nextDate = new Date(now)

  switch (unit) {
    case 'day': case 'days':
      if (value % 7 === 0 && value >= 7) {
        nextDate.setDate(nextDate.getDate() + value)
      } else {
        nextDate.setDate(nextDate.getDate() + value)
      }
      break
    case 'week': case 'weeks': case 'wks': case 'wk':
      nextDate.setDate(nextDate.getDate() + value * 7)
      break
    case 'month': case 'months': case 'mons': case 'mon':
      nextDate.setMonth(nextDate.getMonth() + value)
      break
    case 'year': case 'years': case 'yrs': case 'yr':
      nextDate.setFullYear(nextDate.getFullYear() + value)
      break
    case 'hour': case 'hours': case 'hrs': case 'hr':
      nextDate.setHours(nextDate.getHours() + value)
      break
    case 'minute': case 'minutes': case 'mins': case 'min':
      nextDate.setMinutes(nextDate.getMinutes() + value)
      break
    default:
      return null
  }
  return nextDate
}

function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initialBoardId = null, boardDeleted = false }) {
  const { authFetch } = useAuth()
  const [boards, setBoards] = useState([])

  const getInitialBoardId = () => {
    if (initialBoardId) return initialBoardId
    try {
      const saved = localStorage.getItem(SELECTED_BOARD_KEY)
      if (saved) {
        const boardId = parseInt(saved, 10)
        if (!isNaN(boardId)) return boardId
      }
    } catch (err) {}
    return null
  }

  const hasBoardsCache = () => {
    try {
      const cached = localStorage.getItem(BOARDS_CACHE_KEY)
      if (cached) {
        const data = JSON.parse(cached)
        return !!(data.boards && data.boards.length >= 0)
      }
    } catch (err) {}
    return false
  }

  const [selectedBoardId, setSelectedBoardIdState] = useState(getInitialBoardId)
  const [items, setItems] = useState([])
  const [loading, setLoading] = useState(true)
  const [boardsLoading, setBoardsLoading] = useState(!hasBoardsCache())
  const [error, setError] = useState('')
  const [selectedItemForDetail, setSelectedItemForDetail] = useState(null)
  const [selectedItemForPostpone, setSelectedItemForPostpone] = useState(null)
  const [postponeDate, setPostponeDate] = useState('')
  const [isPostponing, setIsPostponing] = useState(false)
  const [toast, setToast] = useState(null)
  const fetchingRef = useRef(false)
  const initialFetchDoneRef = useRef(false)
  const prevIsActiveRef = useRef(isActive)

  // Refs для закрытия диалогов кнопкой "Назад"
  const historyPushedForDetailRef = useRef(false)
  const historyPushedForPostponeRef = useRef(false)
  const selectedItemForDetailRef = useRef(selectedItemForDetail)
  const selectedItemForPostponeRef = useRef(selectedItemForPostpone)

  const setSelectedBoardId = (boardId) => {
    setSelectedBoardIdState(boardId)
    try {
      if (boardId) {
        localStorage.setItem(SELECTED_BOARD_KEY, String(boardId))
      } else {
        localStorage.removeItem(SELECTED_BOARD_KEY)
      }
    } catch (err) {}
  }

  // Загрузка досок
  const fetchBoards = async (showLoading = true) => {
    if (showLoading) setBoardsLoading(true)
    try {
      const res = await authFetch('/api/shopping/boards')
      if (res.ok) {
        const data = await res.json()
        const boardsList = Array.isArray(data) ? data : []
        setBoards(boardsList)

        try {
          localStorage.setItem(BOARDS_CACHE_KEY, JSON.stringify({ boards: boardsList }))
        } catch (err) {}

        if (boardDeleted || !boardsList.some(b => b.id === selectedBoardId)) {
          if (boardsList.length > 0) {
            setSelectedBoardId(boardsList[0].id)
          } else {
            setSelectedBoardId(null)
          }
        }
      }
    } catch (err) {
      setError('Ошибка загрузки досок')
    } finally {
      setBoardsLoading(false)
    }
  }

  // Загрузка товаров
  const fetchItems = async (boardId) => {
    if (!boardId || fetchingRef.current) return
    fetchingRef.current = true
    setLoading(true)
    setError('')

    try {
      const res = await authFetch(`/api/shopping/boards/${boardId}/items`)
      if (res.ok) {
        const data = await res.json()
        setItems(Array.isArray(data) ? data : [])
        try {
          localStorage.setItem(`${ITEMS_CACHE_KEY}_${boardId}`, JSON.stringify(data))
        } catch (err) {}
      } else {
        setError('Ошибка загрузки товаров')
      }
    } catch (err) {
      setError('Ошибка загрузки товаров')
    } finally {
      setLoading(false)
      fetchingRef.current = false
    }
  }

  // Загрузка из кэша
  useEffect(() => {
    try {
      const cached = localStorage.getItem(BOARDS_CACHE_KEY)
      if (cached) {
        const data = JSON.parse(cached)
        if (data.boards) setBoards(data.boards)
      }
    } catch (err) {}

    if (selectedBoardId) {
      try {
        const cached = localStorage.getItem(`${ITEMS_CACHE_KEY}_${selectedBoardId}`)
        if (cached) {
          setItems(JSON.parse(cached) || [])
        }
      } catch (err) {}
    }
  }, [])

  // Начальная загрузка
  useEffect(() => {
    const hasCache = hasBoardsCache()
    fetchBoards(!hasCache)
    initialFetchDoneRef.current = true
  }, [])

  // Загрузка при смене доски
  useEffect(() => {
    if (selectedBoardId) {
      fetchItems(selectedBoardId)
    } else {
      setItems([])
      setLoading(false)
    }
  }, [selectedBoardId])

  // Рефреш при возврате на таб
  useEffect(() => {
    if (isActive && !prevIsActiveRef.current && initialFetchDoneRef.current) {
      fetchBoards(false)
      if (selectedBoardId) fetchItems(selectedBoardId)
    }
    prevIsActiveRef.current = isActive
  }, [isActive])

  // Рефреш по триггеру
  useEffect(() => {
    if (refreshTrigger > 0) {
      fetchBoards(false)
      if (selectedBoardId) fetchItems(selectedBoardId)
    }
  }, [refreshTrigger])

  // initialBoardId
  useEffect(() => {
    if (initialBoardId) {
      setSelectedBoardId(initialBoardId)
    }
  }, [initialBoardId])

  // Синхронизация refs для диалогов
  useEffect(() => {
    selectedItemForDetailRef.current = selectedItemForDetail
    selectedItemForPostponeRef.current = selectedItemForPostpone
  }, [selectedItemForDetail, selectedItemForPostpone])

  // Закрытие диалогов кнопкой "Назад" (browser history API)
  useEffect(() => {
    if (selectedItemForPostpone && !historyPushedForPostponeRef.current) {
      window.history.pushState({ modalOpen: true, type: 'shopping-postpone' }, '', window.location.href)
      historyPushedForPostponeRef.current = true
    } else if (!selectedItemForPostpone) {
      historyPushedForPostponeRef.current = false
    }

    if (selectedItemForDetail && !historyPushedForDetailRef.current) {
      window.history.pushState({ modalOpen: true, type: 'shopping-detail' }, '', window.location.href)
      historyPushedForDetailRef.current = true
    } else if (!selectedItemForDetail) {
      historyPushedForDetailRef.current = false
    }

    if (!selectedItemForDetail && !selectedItemForPostpone) return

    const handlePopState = () => {
      const currentDetail = selectedItemForDetailRef.current
      const currentPostpone = selectedItemForPostponeRef.current

      if (currentPostpone) {
        setSelectedItemForPostpone(null)
        setPostponeDate('')
        historyPushedForPostponeRef.current = false
        if (currentDetail) {
          window.history.pushState({ modalOpen: true, type: 'shopping-detail' }, '', window.location.href)
        }
        return
      }

      if (currentDetail) {
        setSelectedItemForDetail(null)
        historyPushedForDetailRef.current = false
      }
    }

    window.addEventListener('popstate', handlePopState)
    return () => {
      window.removeEventListener('popstate', handlePopState)
    }
  }, [selectedItemForDetail, selectedItemForPostpone])

  // Фильтрация и группировка на клиенте
  const groupedItems = useMemo(() => {
    const now = new Date()
    now.setHours(0, 0, 0, 0)
    const todayEnd = new Date(now)
    todayEnd.setHours(23, 59, 59, 999)

    const groups = {}

    items.forEach(item => {
      const groupKey = item.group_name || 'Остальные'
      if (!groups[groupKey]) {
        groups[groupKey] = { active: [], future: [] }
      }

      if (!item.next_show_at) {
        groups[groupKey].future.push(item)
        return
      }
      const showAt = new Date(item.next_show_at)
      if (showAt > todayEnd) {
        groups[groupKey].future.push(item)
        return
      }
      groups[groupKey].active.push(item)
    })

    // Сортируем future по next_show_at ASC
    Object.values(groups).forEach(group => {
      group.future.sort((a, b) => {
        if (!a.next_show_at) return 1
        if (!b.next_show_at) return -1
        return new Date(a.next_show_at) - new Date(b.next_show_at)
      })
    })

    return groups
  }, [items])

  const [expandedFuture, setExpandedFuture] = useState({})

  const handleBoardChange = (boardId) => {
    setSelectedBoardId(boardId)
  }

  const handleBoardEdit = () => {
    if (selectedBoardId) {
      const board = boards.find(b => b.id === selectedBoardId)
      if (board?.is_owner) {
        onNavigate('shopping-board-form', { boardId: selectedBoardId })
      } else {
        if (window.confirm('Покинуть доску?')) {
          authFetch(`/api/shopping/boards/${selectedBoardId}/leave`, { method: 'POST' })
            .then(res => {
              if (res.ok) {
                fetchBoards()
              }
            })
        }
      }
    }
  }

  const handleAddBoard = () => {
    onNavigate('shopping-board-form')
  }

  const handleRefresh = () => {
    if (selectedBoardId) fetchItems(selectedBoardId)
  }

  const handleCloseDetail = (skipHistoryBack = false) => {
    if (!skipHistoryBack && historyPushedForDetailRef.current) {
      window.history.back()
    } else {
      historyPushedForDetailRef.current = false
      setSelectedItemForDetail(null)
    }
  }

  const openPostpone = (item) => {
    setSelectedItemForPostpone(item)
    // Предвыбираем дату "по плану" если она не совпадает с текущей next_show_at
    const now2 = new Date()
    now2.setHours(0, 0, 0, 0)
    let planned
    if (item.repetition_period) {
      planned = calculateNextDateFromRepetitionPeriod(item.repetition_period)
    }
    if (!planned) {
      planned = new Date(now2)
      planned.setDate(planned.getDate() + 1)
    }
    planned.setHours(0, 0, 0, 0)
    const plannedStr = formatDateToLocal(planned)
    let nextShowStr = null
    if (item.next_show_at) {
      nextShowStr = formatDateToLocal(new Date(item.next_show_at))
    }
    if (plannedStr !== nextShowStr) {
      setPostponeDate(plannedStr)
    } else {
      setPostponeDate('')
    }
  }

  // Модалка переноса
  const handlePostponeClose = () => {
    if (historyPushedForPostponeRef.current) {
      window.history.back()
    } else {
      historyPushedForPostponeRef.current = false
      setSelectedItemForPostpone(null)
      setPostponeDate('')
    }
  }

  const handleDateSelect = (date) => {
    if (date) {
      setPostponeDate(formatDateToLocal(date))
    }
  }

  const handleDayClick = (date) => {
    if (date) {
      const dateStr = formatDateToLocal(date)
      handlePostponeSubmitWithDate(dateStr)
    }
  }

  const handlePostponeSubmitWithDate = async (dateStr) => {
    if (!selectedItemForPostpone || !dateStr) return

    setIsPostponing(true)
    try {
      const nextShowAt = new Date(dateStr + 'T00:00:00')
      const res = await authFetch(`/api/shopping/items/${selectedItemForPostpone.id}/postpone`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ next_show_at: nextShowAt.toISOString() })
      })
      if (res.ok) {
        setToast({ message: 'Дата перенесена', type: 'success' })
        handleRefresh()
        handlePostponeClose()
      } else {
        setToast({ message: 'Ошибка переноса', type: 'error' })
      }
    } catch (err) {
      setToast({ message: 'Ошибка переноса', type: 'error' })
    } finally {
      setIsPostponing(false)
    }
  }

  const handleTodayClick = () => {
    handlePostponeSubmitWithDate(formatDateToLocal(new Date()))
  }

  const handleTomorrowClick = () => {
    const tomorrow = new Date()
    tomorrow.setDate(tomorrow.getDate() + 1)
    handlePostponeSubmitWithDate(formatDateToLocal(tomorrow))
  }

  const handleWithoutDateClick = async () => {
    if (!selectedItemForPostpone) return
    setIsPostponing(true)
    try {
      const res = await authFetch(`/api/shopping/items/${selectedItemForPostpone.id}/postpone`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ next_show_at: null })
      })
      if (res.ok) {
        setToast({ message: 'Дата убрана', type: 'success' })
        handleRefresh()
        handlePostponeClose()
      }
    } catch (err) {
      setToast({ message: 'Ошибка', type: 'error' })
    } finally {
      setIsPostponing(false)
    }
  }


  const groupNames = useMemo(() => {
    const names = Object.keys(groupedItems)
    return names.sort((a, b) => {
      const groupA = groupedItems[a]
      const groupB = groupedItems[b]
      const hasActiveA = groupA.active.length > 0
      const hasActiveB = groupB.active.length > 0

      if (hasActiveA && !hasActiveB) return -1
      if (!hasActiveA && hasActiveB) return 1

      if (a === 'Остальные') return 1
      if (b === 'Остальные') return -1
      return a.localeCompare(b, 'ru')
    })
  }, [groupedItems])

  const toggleFuture = (groupName) => {
    setExpandedFuture(prev => ({
      ...prev,
      [groupName]: !prev[groupName]
    }))
  }

  return (
    <div className="shopping-list">
      <div className="shopping-header">
        <BoardSelector
          boards={boards}
          selectedBoardId={selectedBoardId}
          onBoardChange={handleBoardChange}
          onBoardEdit={handleBoardEdit}
          onAddBoard={handleAddBoard}
          loading={boardsLoading}
          showBoardAction={false}
        />
        <button className="shopping-close-btn" onClick={() => window.history.back()}>✕</button>
      </div>

      {boards.length === 0 && !boardsLoading && (
        <div className="shopping-empty">
          <p>Нет досок</p>
          <p className="shopping-empty-hint">Создайте доску, чтобы начать добавлять товары</p>
        </div>
      )}

      {selectedBoardId && error && (
        <LoadingError onRetry={handleRefresh} />
      )}

      {selectedBoardId && !error && (
        <>
          {loading && items.length === 0 && (
            <div className="shopping-loading">
              <div className="w-8 h-8 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin"></div>
            </div>
          )}

          {!loading && items.length === 0 && (
            <div className="shopping-empty">
              <p>Нет товаров</p>
            </div>
          )}

          {groupNames.map(groupName => {
            const group = groupedItems[groupName]
            const hasActive = group.active.length > 0
            const hasFuture = group.future.length > 0
            const isFutureExpanded = expandedFuture[groupName]

            return (
              <div key={groupName} className={`project-group ${!hasActive ? 'project-group-no-tasks' : ''}`}>
                <div
                  className={`project-group-header ${hasFuture ? 'project-group-header-clickable' : ''}`}
                  onClick={hasFuture ? () => toggleFuture(groupName) : undefined}
                >
                  <h3 className={`project-group-title ${!hasActive ? 'project-group-title-empty' : ''}`}>{groupName}</h3>
                  {hasFuture ? (
                    <button
                      className="completed-toggle-header"
                      onClick={(e) => {
                        e.stopPropagation()
                        toggleFuture(groupName)
                      }}
                      title={isFutureExpanded ? 'Скрыть ожидающие' : 'Показать ожидающие'}
                    >
                      <span className="completed-toggle-icon">
                        {isFutureExpanded ? '▼' : '▶'}
                      </span>
                    </button>
                  ) : (
                    <div className="completed-toggle-header" style={{ visibility: 'hidden', pointerEvents: 'none' }}>
                      <span className="completed-toggle-icon">▶</span>
                    </div>
                  )}
                </div>

                {hasActive && (
                  <div className="task-group">
                    {group.active.map(item => {
                      let dateDisplay = null
                      if (item.next_show_at) {
                        const itemDate = new Date(item.next_show_at)
                        const now = new Date()
                        now.setHours(0, 0, 0, 0)
                        const target = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate())
                        if (target > now) {
                          dateDisplay = formatDateForDisplay(item.next_show_at)
                        }
                      }

                      return (
                        <div
                          key={item.id}
                          className="task-item"
                          onClick={() => setSelectedItemForDetail(item.id)}
                        >
                          <div className="task-item-content">
                            <div
                              className="task-checkmark"
                              onClick={(e) => {
                                e.stopPropagation()
                                setSelectedItemForDetail(item.id)
                              }}
                              title="Выполнить"
                            >
                              <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <circle cx="10" cy="10" r="9" stroke="currentColor" strokeWidth="2" fill="none" className="checkmark-circle" />
                                <path d="M6 10 L9 13 L14 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="checkmark-check" />
                              </svg>
                            </div>
                            <div className="task-name-container">
                              <div className="task-name-wrapper">
                                <div className="task-name">{item.name}</div>
                                {dateDisplay && (
                                  <div className="task-next-show-date">{dateDisplay}</div>
                                )}
                              </div>
                            </div>
                            <div className="task-actions">
                              <button
                                className="task-postpone-button"
                                onClick={(e) => {
                                  e.stopPropagation()
                                  openPostpone(item)
                                }}
                                title="Перенести"
                              >
                                <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
                                  <circle cx="10" cy="10" r="8" stroke="currentColor" strokeWidth="1.5" fill="none"/>
                                  <path d="M10 5V10L13 12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" fill="none"/>
                                </svg>
                              </button>
                            </div>
                          </div>
                        </div>
                      )
                    })}
                  </div>
                )}

                {hasFuture && isFutureExpanded && (
                  <div className="task-group completed-tasks">
                    {group.future.map(item => {
                      let dateDisplay = null
                      if (item.next_show_at) {
                        const itemDate = new Date(item.next_show_at)
                        const now = new Date()
                        now.setHours(0, 0, 0, 0)
                        const target = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate())
                        if (target > now) {
                          dateDisplay = formatDateForDisplay(item.next_show_at)
                        }
                      }

                      return (
                      <div
                        key={item.id}
                        className="task-item"
                        onClick={() => setSelectedItemForDetail(item.id)}
                      >
                        <div className="task-item-content">
                          <div
                            className="task-checkmark"
                            onClick={(e) => {
                              e.stopPropagation()
                              setSelectedItemForDetail(item.id)
                            }}
                            title="Выполнить"
                          >
                            <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
                              <circle cx="10" cy="10" r="9" stroke="currentColor" strokeWidth="2" fill="none" className="checkmark-circle" />
                              <path d="M6 10 L9 13 L14 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="checkmark-check" />
                            </svg>
                          </div>
                          <div className="task-name-container">
                            <div className="task-name-wrapper">
                              <div className="task-name">{item.name}</div>
                              {dateDisplay && (
                                <div className="task-next-show-date">{dateDisplay}</div>
                              )}
                            </div>
                          </div>
                          <div className="task-actions">
                            <button
                              className="task-postpone-button"
                              onClick={(e) => {
                                e.stopPropagation()
                                setSelectedItemForPostpone(item)
                              }}
                              title="Перенести"
                            >
                              <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <circle cx="10" cy="10" r="8" stroke="currentColor" strokeWidth="1.5" fill="none"/>
                                <path d="M10 5V10L13 12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" fill="none"/>
                              </svg>
                            </button>
                          </div>
                        </div>
                      </div>
                    )})}
                  </div>
                )}
              </div>
            )
          })}
        </>
      )}

      {/* Модалка выполнения */}
      {selectedItemForDetail && (
        <ShoppingItemDetail
          itemId={selectedItemForDetail}
          onClose={handleCloseDetail}
          onRefresh={handleRefresh}
          onItemCompleted={() => setToast({ message: 'Товар выполнен', type: 'success' })}
          onNavigate={onNavigate}
        />
      )}

      {/* Модалка переноса */}
      {selectedItemForPostpone && (() => {
        const todayStr = formatDateToLocal(new Date())
        const tomorrow = new Date()
        tomorrow.setDate(tomorrow.getDate() + 1)
        const tomorrowStr = formatDateToLocal(tomorrow)

        let nextShowAtStr = null
        if (selectedItemForPostpone.next_show_at) {
          const nextShowAtDate = new Date(selectedItemForPostpone.next_show_at)
          nextShowAtStr = formatDateToLocal(nextShowAtDate)
        }

        const isTomorrow = nextShowAtStr === tomorrowStr
        // Показываем "Сегодня" если нет даты, или дата строго в будущем (сегодня и прошлое — не показываем)
        const showTodayChip = !nextShowAtStr || nextShowAtStr > todayStr

        // Дата "по плану"
        const item = selectedItemForPostpone
        let plannedDate
        const now = new Date()
        now.setHours(0, 0, 0, 0)
        if (item.repetition_period) {
          const nextDate = calculateNextDateFromRepetitionPeriod(item.repetition_period)
          if (nextDate) plannedDate = nextDate
        }
        if (!plannedDate) {
          plannedDate = new Date(now)
          plannedDate.setDate(plannedDate.getDate() + 1)
        }
        plannedDate.setHours(0, 0, 0, 0)
        const plannedDateStr = formatDateToLocal(plannedDate)
        const plannedNorm = plannedDateStr.slice(0, 10)
        const nextShowNorm = nextShowAtStr ? String(nextShowAtStr).slice(0, 10) : ''
        const isCurrentDatePlanned = plannedNorm && nextShowNorm && plannedNorm === nextShowNorm

        const modalContent = (
          <div className="task-postpone-modal-overlay" onClick={handlePostponeClose}>
            <div className="task-postpone-modal" onClick={(e) => e.stopPropagation()}>
              <div className="task-postpone-modal-header">
                <h3>{selectedItemForPostpone.name}</h3>
                <button onClick={handlePostponeClose} className="task-postpone-close-button">
                  ✕
                </button>
              </div>
              <div className="task-postpone-modal-content">
                <div className="task-postpone-calendar">
                  <DayPicker
                    mode="single"
                    selected={postponeDate ? new Date(postponeDate + 'T00:00:00') : undefined}
                    onSelect={handleDateSelect}
                    onDayClick={handleDayClick}
                    disabled={{ before: (() => {
                      const today = new Date()
                      today.setHours(0, 0, 0, 0)
                      return today
                    })() }}
                    locale={ru}
                  />
                </div>
                <div className="task-postpone-quick-buttons">
                  {showTodayChip && (
                    <button
                      onClick={handleTodayClick}
                      className="task-postpone-quick-button"
                      disabled={isPostponing}
                    >
                      Сегодня
                    </button>
                  )}
                  {!isTomorrow && (
                    <button
                      onClick={handleTomorrowClick}
                      className="task-postpone-quick-button"
                      disabled={isPostponing}
                    >
                      Завтра
                    </button>
                  )}
                  {!isCurrentDatePlanned && (
                    <button
                      onClick={() => handlePostponeSubmitWithDate(plannedDateStr)}
                      className="task-postpone-quick-button"
                      disabled={isPostponing}
                    >
                      По плану
                    </button>
                  )}
                  {selectedItemForPostpone?.next_show_at && (
                    <button
                      onClick={handleWithoutDateClick}
                      className="task-postpone-quick-button"
                      disabled={isPostponing}
                    >
                      Без даты
                    </button>
                  )}
                </div>
              </div>
            </div>
          </div>
        )

        return typeof document !== 'undefined'
          ? createPortal(modalContent, document.body)
          : modalContent
      })()}

      {toast && (
        <Toast
          message={toast.message}
          type={toast.type}
          onClose={() => setToast(null)}
        />
      )}
    </div>
  )
}

export default ShoppingList
