import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'
import { createPortal } from 'react-dom'
import { useAuth } from './auth/AuthContext'
import LoadingError from './LoadingError'
import Toast from './Toast'
import './TaskDetail.css'

const API_URL = '/api/tasks'

// Функция для проверки, является ли период нулевым
const isZeroPeriod = (intervalStr) => {
  if (!intervalStr) return false
  const trimmed = intervalStr.trim()
  const parts = trimmed.split(/\s+/)
  if (parts.length < 1) return false
  const value = parseInt(parts[0], 10)
  return !isNaN(value) && value === 0
}

// Функция для проверки, является ли repetition_date нулевым
const isZeroDate = (dateStr) => {
  if (!dateStr) return false
  const trimmed = dateStr.trim()
  const parts = trimmed.split(/\s+/)
  if (parts.length < 2) return false
  const value = parts[0]
  const numValue = parseInt(value, 10)
  return !isNaN(numValue) && numValue === 0
}

// Функция для вычисления следующей даты по repetition_date
const calculateNextDateFromRepetitionDate = (repetitionDateStr) => {
  if (!repetitionDateStr) return null
  
  const parts = repetitionDateStr.trim().split(/\s+/)
  if (parts.length < 2) return null
  
  const value = parts[0]
  const unit = parts[1].toLowerCase()
  const now = new Date()
  now.setHours(0, 0, 0, 0)
  
  switch (unit) {
    case 'week': {
      // N-й день недели (1=понедельник, 7=воскресенье)
      const dayOfWeek = parseInt(value, 10)
      if (isNaN(dayOfWeek) || dayOfWeek < 1 || dayOfWeek > 7) return null
      // JavaScript: 0=воскресенье, 1=понедельник... 6=суббота
      // Наш формат: 1=понедельник... 7=воскресенье
      // Конвертируем: наш 1 (Пн) -> JS 1, наш 7 (Вс) -> JS 0
      const targetJsDay = dayOfWeek === 7 ? 0 : dayOfWeek
      const currentJsDay = now.getDay()
      // Вычисляем дни до следующего вхождения (включая сегодня, если ещё не прошло)
      let daysUntil = (targetJsDay - currentJsDay + 7) % 7
      // Если сегодня тот же день, берём следующую неделю
      if (daysUntil === 0) daysUntil = 7
      const nextDate = new Date(now)
      nextDate.setDate(now.getDate() + daysUntil)
      return nextDate
    }
    case 'month': {
      // N-й день месяца
      const dayOfMonth = parseInt(value, 10)
      if (isNaN(dayOfMonth) || dayOfMonth < 1 || dayOfMonth > 31) return null
      
      // Ищем ближайшую дату с этим днём
      let searchDate = new Date(now)
      for (let i = 0; i < 12; i++) {
        const year = searchDate.getFullYear()
        const month = searchDate.getMonth()
        const lastDayOfMonth = new Date(year, month + 1, 0).getDate()
        const actualDay = Math.min(dayOfMonth, lastDayOfMonth)
        const candidateDate = new Date(year, month, actualDay)
        
        if (candidateDate > now) {
          return candidateDate
        }
        // Переходим к следующему месяцу
        searchDate = new Date(year, month + 1, 1)
      }
      return null
    }
    case 'year': {
      // MM-DD формат
      const dateParts = value.split('-')
      if (dateParts.length !== 2) return null
      const monthNum = parseInt(dateParts[0], 10)
      const day = parseInt(dateParts[1], 10)
      if (isNaN(monthNum) || isNaN(day) || monthNum < 1 || monthNum > 12 || day < 1 || day > 31) return null
      
      let year = now.getFullYear()
      let candidateDate = new Date(year, monthNum - 1, day)
      
      if (candidateDate <= now) {
        candidateDate = new Date(year + 1, monthNum - 1, day)
      }
      return candidateDate
    }
    default:
      return null
  }
}

// Функция для вычисления следующей даты по repetition_period
// Поддерживает сокращенные формы единиц времени (например, "mons" для месяцев)
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 'minute':
    case 'minutes':
    case 'mins':
    case 'min':
      nextDate.setMinutes(nextDate.getMinutes() + value)
      break
    case 'hour':
    case 'hours':
    case 'hrs':
    case 'hr':
      nextDate.setHours(nextDate.getHours() + value)
      break
    case 'day':
    case 'days':
      // PostgreSQL может возвращать недели как дни (например, "7 days" вместо "1 week")
      // Если количество дней кратно 7, обрабатываем как недели
      if (value % 7 === 0 && value >= 7) {
        const weeks = value / 7
        nextDate.setDate(nextDate.getDate() + weeks * 7)
      } 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
    default:
      return null
  }
  
  return nextDate
}

// Форматирование даты в YYYY-MM-DD (локальное время, без смещения в UTC)
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 ''
  
  // Парсим дату из формата YYYY-MM-DD
  const dateParts = dateStr.split('-')
  if (dateParts.length !== 3) return dateStr
  
  const yearNum = parseInt(dateParts[0], 10)
  const monthNum = parseInt(dateParts[1], 10) - 1 // месяцы в JS начинаются с 0
  const dayNum = parseInt(dateParts[2], 10)
  
  if (isNaN(yearNum) || isNaN(monthNum) || isNaN(dayNum)) return dateStr
  
  const targetDate = new Date(yearNum, monthNum, dayNum)
  targetDate.setHours(0, 0, 0, 0)
  
  const now = new Date()
  now.setHours(0, 0, 0, 0)
  
  const diffDays = Math.floor((targetDate - now) / (1000 * 60 * 60 * 24))
  
  // Сегодня
  if (diffDays === 0) {
    return 'Сегодня'
  }
  
  // Завтра
  if (diffDays === 1) {
    return 'Завтра'
  }
  
  // Вчера
  if (diffDays === -1) {
    return 'Вчера'
  }
  
  // Дни недели для ближайших дней из будущего (в пределах 7 дней)
  if (diffDays > 0 && diffDays <= 7) {
    const dayNames = ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота']
    const dayOfWeek = targetDate.getDay()
    return dayNames[dayOfWeek]
  }
  
  const monthNames = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 
                     'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']
  
  // Если это число из того же года - только день и месяц
  if (targetDate.getFullYear() === now.getFullYear()) {
    const displayDay = targetDate.getDate()
    const displayMonth = monthNames[targetDate.getMonth()]
    return `${displayDay} ${displayMonth}`
  }
  
  // Для других случаев - полная дата
  const displayDay = targetDate.getDate()
  const displayMonth = monthNames[targetDate.getMonth()]
  const displayYear = targetDate.getFullYear()
  return `${displayDay} ${displayMonth} ${displayYear}`
}

// Функция для форматирования числа как %.4g в Go (до 4 значащих цифр)
const formatScore = (num) => {
  if (num === 0) return '0'
  
  // Используем toPrecision(4) для получения до 4 значащих цифр
  let str = num.toPrecision(4)
  
  // Убираем лишние нули в конце (но оставляем точку если есть цифры после неё)
  str = str.replace(/\.?0+$/, '')
  
  // Если получилась экспоненциальная нотация для больших чисел, конвертируем обратно
  if (str.includes('e+') || str.includes('e-')) {
    const numValue = parseFloat(str)
    // Для чисел >= 10000 используем экспоненциальную нотацию
    if (Math.abs(numValue) >= 10000) {
      return str
    }
    // Для остальных конвертируем в обычное число
    return numValue.toString().replace(/\.?0+$/, '')
  }
  
  return str
}

// Функция для формирования сообщения Telegram в реальном времени
const formatTelegramMessage = (task, rewards, subtasks, selectedSubtasks, progressionValue) => {
  if (!task) return ''

  // Вычисляем score для каждой награды основной задачи
  const rewardStrings = {}
  const progressionBase = task.progression_base
  const hasProgression = progressionBase != null
  // Если прогрессия не введена - используем progression_base
  const value = progressionValue && progressionValue.trim() !== '' 
    ? parseFloat(progressionValue) 
    : (hasProgression ? progressionBase : null)

  rewards.forEach(reward => {
    let score = reward.value
    if (reward.use_progression && hasProgression) {
      if (value !== null && !isNaN(value)) {
        score = (value / progressionBase) * reward.value
      } else {
        // Если прогрессия не введена, используем progression_base (score = reward.value)
        score = reward.value
      }
    }

    const scoreStr = score >= 0 
      ? `**${reward.project_name}+${formatScore(score)}**`
      : `**${reward.project_name}-${formatScore(Math.abs(score))}**`
    rewardStrings[reward.position] = scoreStr
  })

  // Функция для замены плейсхолдеров
  const replacePlaceholders = (message, rewardStrings) => {
    let result = message
    // Сначала защищаем экранированные плейсхолдеры
    const escapedMarkers = {}
    for (let i = 0; i < 100; i++) {
      const escaped = `\\$${i}`
      const marker = `__ESCAPED_DOLLAR_${i}__`
      if (result.includes(escaped)) {
        escapedMarkers[marker] = escaped
        result = result.replace(new RegExp(escaped.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), marker)
      }
    }
    // Заменяем ${0}, ${1}, и т.д.
    for (let i = 0; i < 100; i++) {
      const placeholder = `\${${i}}`
      if (rewardStrings[i]) {
        result = result.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), rewardStrings[i])
      }
    }
    // Заменяем $0, $1, и т.д. (с конца, чтобы не заменить $1 в $10)
    for (let i = 99; i >= 0; i--) {
      if (rewardStrings[i]) {
        const searchStr = `$${i}`
        const regex = new RegExp(`\\$${i}(?!\\d)`, 'g')
        result = result.replace(regex, rewardStrings[i])
      }
    }
    // Восстанавливаем экранированные
    Object.entries(escapedMarkers).forEach(([marker, escaped]) => {
      result = result.replace(new RegExp(marker, 'g'), escaped)
    })
    return result
  }

  // Формируем сообщение основной задачи
  let mainTaskMessage = task.reward_message && task.reward_message.trim() !== ''
    ? replacePlaceholders(task.reward_message, rewardStrings)
    : task.name

  // Формируем сообщения подзадач
  const subtaskMessages = []
  subtasks.forEach(subtask => {
    if (!selectedSubtasks.has(subtask.task.id)) return
    if (!subtask.task.reward_message || subtask.task.reward_message.trim() === '') return

    // Вычисляем score для наград подзадачи
    const subtaskRewardStrings = {}
    subtask.rewards.forEach(reward => {
      let score = reward.value
      const subtaskProgressionBase = subtask.task.progression_base
      if (reward.use_progression) {
        if (subtaskProgressionBase != null && value !== null && !isNaN(value)) {
          score = (value / subtaskProgressionBase) * reward.value
        } else if (hasProgression && value !== null && !isNaN(value)) {
          score = (value / progressionBase) * reward.value
        } else if (subtaskProgressionBase != null) {
          // Если прогрессия не введена, используем progression_base подзадачи (score = reward.value)
          score = reward.value
        } else if (hasProgression) {
          // Если у подзадачи нет progression_base, используем основной (score = reward.value)
          score = reward.value
        }
      }

      const scoreStr = score >= 0
        ? `**${reward.project_name}+${formatScore(score)}**`
        : `**${reward.project_name}-${formatScore(Math.abs(score))}**`
      subtaskRewardStrings[reward.position] = scoreStr
    })

    const subtaskMessage = replacePlaceholders(subtask.task.reward_message, subtaskRewardStrings)
    subtaskMessages.push(subtaskMessage)
  })

  // Формируем итоговое сообщение
  let finalMessage = mainTaskMessage
  subtaskMessages.forEach(subtaskMsg => {
    finalMessage += '\n + ' + subtaskMsg
  })

  return finalMessage
}

function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted, onNavigate }) {
  const { authFetch } = useAuth()
  const [taskDetail, setTaskDetail] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)
  const [selectedSubtasks, setSelectedSubtasks] = useState(new Set())
  const [progressionValue, setProgressionValue] = useState('')
  const [isCompleting, setIsCompleting] = useState(false)
  const [toastMessage, setToastMessage] = useState(null)
  const [wishlistInfo, setWishlistInfo] = useState(null)
  const [isSaving, setIsSaving] = useState(false)
  const [completeAtEndOfDay, setCompleteAtEndOfDay] = useState(false)

  const fetchTaskDetail = useCallback(async () => {
    try {
      setLoading(true)
      setError(null)
      const response = await authFetch(`${API_URL}/${taskId}`)
      if (!response.ok) {
        throw new Error('Ошибка загрузки задачи')
      }
      const data = await response.json()
      setTaskDetail(data)
      
      // Используем информацию о wishlist из ответа API
      if (data.wishlist_info) {
        setWishlistInfo({
          id: data.wishlist_info.id,
          name: data.wishlist_info.name,
          unlocked: data.wishlist_info.unlocked || false
        })
      } else {
        setWishlistInfo(null)
      }

      // Предзаполнение данных из драфта
      if (data.draft_progression_value != null) {
        setProgressionValue(data.draft_progression_value.toString())
      }
      
      if (data.draft_subtasks && data.draft_subtasks.length > 0) {
        // Создаем Set из ID подзадач из драфта
        const draftSubtaskIDs = new Set(data.draft_subtasks.map(ds => ds.subtask_id))
        // Фильтруем только те подзадачи, которые существуют в текущих подзадачах задачи
        const validSubtaskIDs = new Set()
        if (data.subtasks) {
          data.subtasks.forEach(subtask => {
            if (draftSubtaskIDs.has(subtask.task.id)) {
              validSubtaskIDs.add(subtask.task.id)
            }
          })
        }
        setSelectedSubtasks(validSubtaskIDs)
      }

      // Значение чекбокса будет установлено в useEffect при изменении taskDetail
    } catch (err) {
      setError(err.message)
      console.error('Error fetching task detail:', err)
    } finally {
      setLoading(false)
    }
  }, [taskId, authFetch])

  useEffect(() => {
    if (taskId) {
      fetchTaskDetail()
    } else {
      // Сбрасываем состояние при закрытии модального окна
      setTaskDetail(null)
      setLoading(true)
      setError(null)
      setSelectedSubtasks(new Set())
      setProgressionValue('')
      setCompleteAtEndOfDay(false)
    }
  }, [taskId, fetchTaskDetail])

  const handleSubtaskToggle = (subtaskId) => {
    setSelectedSubtasks(prev => {
      const newSet = new Set(prev)
      if (newSet.has(subtaskId)) {
        newSet.delete(subtaskId)
      } else {
        newSet.add(subtaskId)
      }
      return newSet
    })
  }

  const handleSave = async () => {
    if (!taskDetail) return

    // Если чекбокс включен - выполняем в конце дня, иначе сохраняем без автовыполнения
    const autoComplete = completeAtEndOfDay

    setIsSaving(true)
    try {
      const payload = {
        auto_complete: autoComplete,
        children_task_ids: Array.from(selectedSubtasks)
      }

      // Если есть прогрессия, отправляем значение (или null, если не введено)
      if (taskDetail.task.progression_base != null) {
        if (progressionValue.trim()) {
          const parsedValue = parseFloat(progressionValue)
          if (isNaN(parsedValue)) {
            throw new Error('Неверное значение')
          }
          payload.progression_value = parsedValue
        } else {
          // Если прогрессия не введена - отправляем null
          payload.progression_value = null
        }
      } else {
        // Если нет progression_base, но пользователь ввел значение - отправляем его
        if (progressionValue.trim()) {
          const parsedValue = parseFloat(progressionValue)
          if (!isNaN(parsedValue)) {
            payload.progression_value = parsedValue
          }
        }
      }

      const endpoint = autoComplete
        ? `${API_URL}/${taskId}/complete-at-end-of-day`
        : `${API_URL}/${taskId}/draft`

      const response = await authFetch(endpoint, {
        method: autoComplete ? 'POST' : 'PUT',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}))
        throw new Error(errorData.message || 'Ошибка при сохранении драфта')
      }

      setToastMessage({ 
        text: autoComplete 
          ? 'Задача будет выполнена в конце дня' 
          : 'Драфт сохранен', 
        type: 'success' 
      })

      // Обновляем данные задачи, чтобы получить актуальное значение auto_complete
      await fetchTaskDetail()

      // Обновляем данные задачи в списке
      if (onRefresh) {
        onRefresh()
      }

      // Закрываем модальное окно после успешного сохранения
      if (onClose) {
        onClose()
      }
    } catch (err) {
      console.error('Error saving draft:', err)
      setToastMessage({ text: err.message || 'Ошибка при сохранении драфта', type: 'error' })
    } finally {
      setIsSaving(false)
    }
  }

  const handleComplete = async () => {
    if (!taskDetail) return

    // Проверяем, что желание разблокировано (если есть связанное желание)
    if (wishlistInfo && !wishlistInfo.unlocked) {
      setToastMessage({ text: 'Невозможно выполнить задачу: желание не разблокировано', type: 'error' })
      return
    }

    setIsCompleting(true)
    try {
      const payload = {
        children_task_ids: Array.from(selectedSubtasks)
      }

      // Если есть прогрессия, отправляем значение (или progression_base, если не введено)
      if (taskDetail.task.progression_base != null) {
        if (progressionValue.trim()) {
          payload.value = parseFloat(progressionValue)
          if (isNaN(payload.value)) {
            throw new Error('Неверное значение')
          }
        } else {
          // Если прогрессия не введена - используем progression_base
          payload.value = taskDetail.task.progression_base
        }
      }

      const endpoint = `${API_URL}/${taskId}/complete`

      const response = await authFetch(endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}))
        throw new Error(errorData.message || 'Ошибка при выполнении задачи')
      }

      // Показываем уведомление о выполнении
      if (onTaskCompleted) {
        onTaskCompleted()
      }

      // Обновляем список и закрываем модальное окно
      if (onRefresh) {
        onRefresh()
      }
      if (onClose) {
        onClose()
      }
    } catch (err) {
      console.error('Error completing task:', err)
      setToastMessage({ text: err.message || 'Ошибка при выполнении задачи', type: 'error' })
    } finally {
      setIsCompleting(false)
    }
  }

  const handleCompleteFinally = async () => {
    if (!taskDetail) return

    // Проверяем, что желание разблокировано (если есть связанное желание)
    if (wishlistInfo && !wishlistInfo.unlocked) {
      setToastMessage({ text: 'Невозможно выполнить задачу: желание не разблокировано', type: 'error' })
      return
    }

    setIsCompleting(true)
    try {
      const payload = {
        children_task_ids: Array.from(selectedSubtasks)
      }

      // Если есть прогрессия, отправляем значение (или progression_base, если не введено)
      if (taskDetail.task.progression_base != null) {
        if (progressionValue.trim()) {
          payload.value = parseFloat(progressionValue)
          if (isNaN(payload.value)) {
            throw new Error('Неверное значение')
          }
        } else {
          // Если прогрессия не введена - используем progression_base
          payload.value = taskDetail.task.progression_base
        }
      }

      const endpoint = `${API_URL}/${taskId}/complete-and-delete`

      const response = await authFetch(endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}))
        throw new Error(errorData.message || 'Ошибка при выполнении задачи')
      }

      // Показываем уведомление о выполнении
      if (onTaskCompleted) {
        onTaskCompleted()
      }

      // Обновляем список и закрываем модальное окно
      if (onRefresh) {
        onRefresh()
      }
      if (onClose) {
        onClose()
      }
    } catch (err) {
      console.error('Error completing task:', err)
      setToastMessage({ text: err.message || 'Ошибка при выполнении задачи', type: 'error' })
    } finally {
      setIsCompleting(false)
    }
  }

  if (!taskId) return null

  const { task, rewards, subtasks } = taskDetail || {}
  const hasProgression = task?.progression_base != null
  // Кнопка активна только если желание разблокировано (или задачи нет связанного желания)
  const canComplete = !wishlistInfo || wishlistInfo.unlocked
  const hasProgressionOrSubtasks = hasProgression || (subtasks && subtasks.length > 0)

  // Определяем, является ли задача одноразовой
  // Одноразовая задача: когда оба поля null/undefined (из бэкенда видно, что в этом случае задача помечается как deleted)
  // Бесконечная задача: когда хотя бы одно поле равно "0 day" или "0 week" и т.д.
  // Повторяющаяся задача: когда есть значение (не null и не 0)
  // Кнопка "Закрыть" показывается для задач, которые НЕ одноразовые (имеют повторение, даже если оно равно 0)
  // Проверяем, что оба поля отсутствуют (null или undefined)
  const isOneTime = (task?.repetition_period == null || task?.repetition_period === undefined) && 
                    (task?.repetition_date == null || task?.repetition_date === undefined)

  // Вычисляем следующую дату для неодноразовых задач
  const nextTaskDate = useMemo(() => {
    if (!task || isOneTime) return null
    
    const now = new Date()
    now.setHours(0, 0, 0, 0)
    
    let nextDate = null
    
    if (task.repetition_date) {
      // Для задач с repetition_date - вычисляем следующую подходящую дату
      nextDate = calculateNextDateFromRepetitionDate(task.repetition_date)
    } else if (task.repetition_period && !isZeroPeriod(task.repetition_period)) {
      // Для задач с repetition_period (не нулевым) - вычисляем следующую дату
      nextDate = calculateNextDateFromRepetitionPeriod(task.repetition_period)
    }
    
    if (!nextDate) return null
    
    nextDate.setHours(0, 0, 0, 0)
    return formatDateForDisplay(formatDateToLocal(nextDate))
  }, [task, isOneTime])

  // Формируем сообщение для Telegram в реальном времени
  const telegramMessage = useMemo(() => {
    if (!taskDetail) return ''
    return formatTelegramMessage(task, rewards || [], subtasks || [], selectedSubtasks, progressionValue)
  }, [taskDetail, task, rewards, subtasks, selectedSubtasks, progressionValue])

  // Обновляем значение чекбокса при изменении taskDetail
  useEffect(() => {
    if (taskDetail && taskDetail.task) {
      const autoCompleteValue = Boolean(taskDetail.task.auto_complete)
      console.log('useEffect: Updating completeAtEndOfDay from taskDetail:', autoCompleteValue, 'task.auto_complete:', taskDetail.task.auto_complete)
      setCompleteAtEndOfDay(autoCompleteValue)
    } else {
      setCompleteAtEndOfDay(false)
    }
  }, [taskDetail])



  const modalContent = (
    <div className="task-detail-modal-overlay" onClick={onClose}>
      <div className="task-detail-modal" onClick={(e) => e.stopPropagation()}>
        <div className="task-detail-modal-header">
          <h2 
            className="task-detail-title"
            onClick={taskDetail ? () => {
              // Закрываем модальное окно БЕЗ history.back() (skipHistoryBack = true)
              // handleTabChange заменит запись модального окна через replaceState
              onClose?.(true)
              onNavigate?.('task-form', { taskId: taskId })
            } : undefined}
            style={{ cursor: taskDetail ? 'pointer' : 'default' }}
          >
            {loading ? 'Загрузка...' : error ? 'Ошибка' : taskDetail ? (
              <>
                {task.name}
                <svg 
                  className="task-detail-edit-icon"
                  width="18" 
                  height="18" 
                  viewBox="0 0 24 24" 
                  fill="none" 
                  stroke="currentColor" 
                  strokeWidth="2" 
                  strokeLinecap="round" 
                  strokeLinejoin="round"
                >
                  <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path>
                </svg>
              </>
            ) : 'Задача'}
          </h2>
          <button onClick={onClose} className="task-detail-close-button">
            ✕
          </button>
        </div>

        <div className="task-detail-modal-content">
          {loading && (
            <div className="loading">Загрузка...</div>
          )}

          {error && !loading && (
            <LoadingError onRetry={fetchTaskDetail} />
          )}

          {!loading && !error && taskDetail && (
            <>
              {/* Информация о связанном желании */}
              {task.wishlist_id && wishlistInfo && (
                <div className="task-wishlist-link">
                  <div className="task-wishlist-link-info">
                    <svg width="20" height="20" 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 className="task-wishlist-link-label">Связано с желанием:</span>
                    <button
                      onClick={() => {
                        if (onClose) onClose()
                        if (onNavigate && wishlistInfo) {
                          onNavigate('wishlist-detail', { wishlistId: wishlistInfo.id })
                        }
                      }}
                      className="task-wishlist-link-button"
                    >
                      {wishlistInfo.name}
                    </button>
                  </div>
                </div>
              )}

              {/* Поле ввода прогрессии */}
              {hasProgression && (
                <div className="progression-section">
                  <label className="progression-label">Значение прогрессии</label>
                  <input
                    type="number"
                    step="any"
                    value={progressionValue}
                    onChange={(e) => setProgressionValue(e.target.value)}
                    placeholder={task.progression_base?.toString() || ''}
                    className="progression-input"
                  />
                </div>
              )}

              {/* Список подзадач */}
              {subtasks && subtasks.length > 0 && (
                <div className="task-subtasks">
                  {subtasks.map((subtask) => {
                    const subtaskName = subtask.task.name || 'Подзадача'
                    return (
                      <div key={subtask.task.id} className="subtask-item">
                        <label className="subtask-checkbox-label">
                          <input
                            type="checkbox"
                            checked={selectedSubtasks.has(subtask.task.id)}
                            onChange={() => handleSubtaskToggle(subtask.task.id)}
                            className="subtask-checkbox"
                          />
                          <div className="subtask-content">
                            <div className="subtask-name">{subtaskName}</div>
                          </div>
                        </label>
                      </div>
                    )
                  })}
                </div>
              )}

              {/* Разделитель - показываем только если есть контент перед ним */}
              {(task.wishlist_id || hasProgression || (subtasks && subtasks.length > 0)) && (
                <div className="task-detail-divider"></div>
              )}

              {/* Сообщение награды */}
              <div className="telegram-message-preview">
                <div className="telegram-message-label">Сообщение награды:</div>
                <div className="telegram-message-text" dangerouslySetInnerHTML={{
                  __html: telegramMessage
                    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
                    .replace(/\n/g, '<br>')
                }} />
              </div>

              {/* Кнопки действий */}
              <div className="task-actions-section">
                {/* Чекбокс над кнопками */}
                <div className="complete-at-end-of-day-checkbox">
                  <label className="checkbox-label">
                    <input
                      type="checkbox"
                      checked={completeAtEndOfDay}
                      onChange={(e) => {
                        console.log('Checkbox changed to:', e.target.checked)
                        setCompleteAtEndOfDay(e.target.checked)
                      }}
                      disabled={isSaving || !canComplete}
                      className="checkbox-input"
                    />
                    <span>Выполнить в конце дня</span>
                  </label>
                </div>
                
                <div className="task-actions-buttons">
                  {/* Левая часть: кнопка "Выполнить" */}
                  <div className="task-action-left">
                    <button
                      onClick={handleComplete}
                      disabled={isCompleting || !canComplete}
                      className="action-button action-button-check"
                      title={!canComplete && wishlistInfo ? 'Желание не разблокировано' : 'Выполнить'}
                    >
                      Выполнить
                    </button>
                  </div>
                  
                  {/* Правая часть: кнопка "Сохранить" */}
                  <div className="task-action-complete-buttons">
                    <button
                      onClick={handleSave}
                      disabled={isSaving || !canComplete}
                      className="action-button action-button-save"
                      title={!canComplete && wishlistInfo ? 'Желание не разблокировано' : ''}
                    >
                      {isSaving ? 'Сохранение...' : 'Сохранить'}
                    </button>
                  </div>
                </div>
                
                {/* Дата слева */}
                {!isOneTime && nextTaskDate && (
                  <div className="next-task-date-info">
                    Следующая: <span className="next-task-date-bold">{nextTaskDate}</span>
                  </div>
                )}
              </div>
            </>
          )}
      </div>
      {toastMessage && (
        <Toast
          message={toastMessage.text}
          type={toastMessage.type}
          onClose={() => setToastMessage(null)}
        />
      )}
    </div>
  </div>
  )

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

export default TaskDetail

