import { patchTemplateApi } from '@/entity/template/api/templateApiService'
import { generateInitialOrder, generateOrder } from '@/lib/template-order'
import { Group, Template } from '@/type/template'
import { useQueryClient } from '@tanstack/react-query'
import { useCallback, useEffect, useState } from 'react'

interface TemplateOrderChange {
  templateId: string
  newOrder: number
  originalOrder: number
  newGroupId?: string | null
  originalGroupId?: string | null
}



const EXPANDED_GROUPS_KEY = 'template-groups-expanded-state'

// Загрузить состояние сворачивания из localStorage
function loadExpandedStatesFromStorage(): Map<string, boolean> {
  try {
    const stored = localStorage.getItem(EXPANDED_GROUPS_KEY)
    if (stored) {
      const parsed = JSON.parse(stored)
      return new Map(Object.entries(parsed))
    }
  } catch (error) {
    console.warn('Ошибка при загрузке состояния групп из localStorage:', error)
  }
  return new Map()
}

// Сохранить состояние сворачивания в localStorage
function saveExpandedStatesToStorage(states: Map<string, boolean>) {
  try {
    const obj = Object.fromEntries(states)
    localStorage.setItem(EXPANDED_GROUPS_KEY, JSON.stringify(obj))
  } catch (error) {
    console.warn('Ошибка при сохранении состояния групп в localStorage:', error)
  }
}

export function useTemplateOrderState(templates: Template[], groups: Group[] = []) {
  const [orderChanges, setOrderChanges] = useState<Map<string, TemplateOrderChange>>(new Map())
  const [groupExpandedStates, setGroupExpandedStates] = useState<Map<string, boolean>>(() => 
    loadExpandedStatesFromStorage()
  )
  const [lastSaveError, setLastSaveError] = useState<string | null>(null)
  const [isSaving, setIsSaving] = useState(false)
  const queryClient = useQueryClient()

  // Очистить состояния для несуществующих групп
  useEffect(() => {
    // Ждем пока группы загрузятся перед очисткой
    if (groups.length === 0) return
    
    const existingGroupIds = new Set(groups.map(g => g.id))
    // Добавляем 'ungrouped' как валидный ключ
    existingGroupIds.add('ungrouped')
    
    const currentStates = new Map(groupExpandedStates)
    let hasChanges = false

    // Удаляем состояния для групп, которых больше нет
    for (const groupId of currentStates.keys()) {
      if (!existingGroupIds.has(groupId)) {
        currentStates.delete(groupId)
        hasChanges = true
      }
    }

    if (hasChanges) {
      setGroupExpandedStates(currentStates)
      saveExpandedStatesToStorage(currentStates)
    }
  }, [groups, groupExpandedStates])

  // Применить изменения порядка локально (для UI)
  const applyOrderChange = useCallback((templateId: string, newOrder: number, newGroupId?: string | null) => {
    const template = templates.find(t => t.id === templateId)
    if (!template) {
      console.log('❌ Template not found for applyOrderChange:', templateId)
      return
    }

    console.log('🔧 applyOrderChange called:', {
      templateId,
      templateName: template.name,
      currentOrder: template.order,
      newOrder,
      currentGroup: template.group_id,
      newGroupId
    })

    setOrderChanges(prev => {
      const newChanges = new Map(prev)
      const originalOrder = template.order ?? 0
      const originalGroupId = template.group_id
      
      console.log('📊 Order change details:', {
        templateId,
        originalOrder,
        newOrder,
        originalGroupId,
        newGroupId,
        orderChanged: newOrder !== originalOrder,
        groupChanged: newGroupId !== originalGroupId
      })
      
      // Если ничего не изменилось, убираем изменение
      if (newOrder === originalOrder && newGroupId === originalGroupId) {
        console.log('🔄 No changes detected, removing from changes map')
        newChanges.delete(templateId)
      } else {
        const change = {
          templateId,
          newOrder,
          originalOrder,
          newGroupId,
          originalGroupId,
        }
        console.log('💾 Storing order change:', change)
        newChanges.set(templateId, change)
      }
      
      console.log('📈 Current changes map size:', newChanges.size)
      console.log('📋 All current changes:', Array.from(newChanges.values()))
      
      return newChanges
    })
  }, [templates])

  // Получить актуальные шаблоны с примененными изменениями
  const getTemplatesWithChanges = useCallback(() => {
    const result = templates.map(template => {
      const change = orderChanges.get(template.id)
      if (change) {
        const modifiedTemplate = { 
          ...template, 
          order: change.newOrder,
          group_id: change.newGroupId !== undefined ? change.newGroupId : template.group_id
        }
        
        // Логируем только если есть изменения
        console.log('🔄 Template with applied changes:', {
          id: template.id,
          name: template.name,
          originalOrder: template.order,
          newOrder: modifiedTemplate.order,
          originalGroup: template.group_id,
          newGroup: modifiedTemplate.group_id
        })
        
        return modifiedTemplate
      }
      return template
    }).sort((a, b) => {
      // Правильная обработка null/undefined порядков  
      const orderA = a.order ?? Number.MAX_SAFE_INTEGER
      const orderB = b.order ?? Number.MAX_SAFE_INTEGER
      return orderA - orderB
    })
    
    return result
  }, [templates, orderChanges])

  // Переключить состояние развертывания группы
  const toggleGroupExpanded = useCallback((groupId: string | null) => {
    // Используем специальный ключ для группы "Без группы"
    const storageKey = groupId || 'ungrouped'
    
    setGroupExpandedStates(prev => {
      const newStates = new Map(prev)
      const currentState = newStates.get(storageKey) ?? true // По умолчанию развернуто
      const newState = !currentState
      newStates.set(storageKey, newState)
      
      // Сохраняем в localStorage
      saveExpandedStatesToStorage(newStates)
      
      return newStates
    })
  }, [])

  // Получить состояние развертывания группы
  const getGroupExpanded = useCallback((groupId: string | null) => {
    // Используем тот же ключ что и в toggleGroupExpanded
    const storageKey = groupId || 'ungrouped'
    return groupExpandedStates.get(storageKey) ?? true // По умолчанию развернуто
  }, [groupExpandedStates])

  // Универсальная обработка drag & drop
  const handleDragEnd = useCallback((activeId: string, overId: string) => {
    if (activeId === overId) return

    const templatesWithChanges = getTemplatesWithChanges()
    const activeTemplate = templatesWithChanges.find(t => t.id === activeId)
    
    if (!activeTemplate) return

    // Проверяем на специальные drop зоны для групп
    if (overId.startsWith('group-drop-')) {
      // Перетаскивание в группу (в конец)
      const targetGroupId = overId === 'group-drop-ungrouped' ? null : overId.replace('group-drop-', '')
      const targetGroupTemplates = templatesWithChanges.filter(t => 
        (t.group_id || null) === (targetGroupId || null)
      )
      const newOrder = generateInitialOrder(targetGroupTemplates, targetGroupId)
      applyOrderChange(activeId, newOrder, targetGroupId)
    } else {
      // Перетаскивание между шаблонами
      const overTemplate = templatesWithChanges.find(t => t.id === overId)
      if (!overTemplate) return

      const targetGroupId = overTemplate.group_id
      const groupTemplates = templatesWithChanges.filter(t => 
        (t.group_id || null) === (targetGroupId || null)
      )
      
      const newOrder = generateOrder(groupTemplates, activeId, overId)
      applyOrderChange(activeId, newOrder, targetGroupId)
    }
  }, [getTemplatesWithChanges, applyOrderChange])

  // Переместить шаблон в группу
  const moveTemplateToGroup = useCallback((templateId: string, targetGroupId: string | null) => {
    const template = templates.find(t => t.id === templateId)
    if (!template) return

    // Генерируем новый порядок для конца целевой группы
    const templatesWithChanges = getTemplatesWithChanges()
    const newOrder = generateInitialOrder(templatesWithChanges, targetGroupId)

    applyOrderChange(templateId, newOrder, targetGroupId)
  }, [templates, getTemplatesWithChanges, applyOrderChange])

  // Сохранить все изменения
  const saveOrderChanges = useCallback(async (
    updateTemplateOrder: (templateId: string, newOrder: number) => Promise<void>,
    moveTemplateToGroupFn: (templateId: string, groupId: string | null) => Promise<void>
  ) => {
    if (orderChanges.size === 0) return

    console.log('💾 SAVING ORDER CHANGES START')
    console.log('📋 Changes to save:', Array.from(orderChanges.values()).map(change => ({
      templateId: change.templateId,
      oldOrder: change.originalOrder,
      newOrder: change.newOrder,
      oldGroup: change.originalGroupId,
      newGroup: change.newGroupId
    })))

    setIsSaving(true)
    setLastSaveError(null)

    try {
      // Группируем изменения по типу
      const orderOnlyChanges: TemplateOrderChange[] = []
      const groupMoveChanges: TemplateOrderChange[] = []
      const combinedChanges: TemplateOrderChange[] = []

      Array.from(orderChanges.values()).forEach(change => {
        if (change.newGroupId !== change.originalGroupId) {
          if (change.newOrder !== change.originalOrder) {
            // Изменились и группа, и порядок
            combinedChanges.push(change)
          } else {
            // Изменилась только группа
            groupMoveChanges.push(change)
          }
        } else {
          // Изменился только порядок
          orderOnlyChanges.push(change)
        }
      })

      // Сначала перемещаем между группами (только изменения группы)
      if (groupMoveChanges.length > 0) {
        const groupMovePromises = groupMoveChanges.map(change =>
          moveTemplateToGroupFn(change.templateId, change.newGroupId || null)
        )
        await Promise.all(groupMovePromises)
      }

      // Комбинированные изменения (группа + порядок) - отправляем один запрос
      if (combinedChanges.length > 0) {
        // Создаем новую функцию для комбинированного обновления
        const combinedPromises = combinedChanges.map(async (change) => {
          const template = templates.find(t => t.id === change.templateId)
          if (!template) throw new Error('Template not found')
          
          console.log('🔧 Combined update (group + order):', {
            templateId: change.templateId,
            newGroupId: change.newGroupId,
            newOrder: change.newOrder
          })
          
          // Отправляем один запрос с обновлением и группы, и порядка
          const patchInput = {
            name: template.name,
            group_id: change.newGroupId === null ? "ungroup" : change.newGroupId,
            order: change.newOrder
          }
          
          // Используем внутренний API вместо двух отдельных вызовов
          const result = await patchTemplateApi(change.templateId, patchInput)
          console.log('Combined update successful:', result)
          return result
        })
        await Promise.all(combinedPromises)
        
        // Инвалидируем кэш после комбинированных обновлений
        queryClient.invalidateQueries({ queryKey: ['templates'] })
      }

      // Сохраняем изменения порядка
      if (orderOnlyChanges.length > 0) {
        console.log('Saving order changes:', orderOnlyChanges)
        const orderPromises = orderOnlyChanges.map(async (change) => {
          try {
            await updateTemplateOrder(change.templateId, change.newOrder)
            console.log(`Successfully updated order for template ${change.templateId}`)
          } catch (error) {
            console.error(`Failed to update order for template ${change.templateId}:`, error)
            throw error
          }
        })
        await Promise.all(orderPromises)
      }
      
      console.log('✅ SAVE ORDER CHANGES SUCCESS - all changes applied')
      
      // Очищаем все сохраненные изменения - они уже применены на сервере
      setOrderChanges(new Map())
    } catch (error) {
      console.error('Ошибка при сохранении изменений:', error)
      setLastSaveError(
        error instanceof Error 
          ? error.message 
          : 'Неизвестная ошибка при сохранении изменений'
      )
    } finally {
      setIsSaving(false)
    }
  }, [orderChanges, queryClient])

  // Отменить все изменения
  const resetOrderChanges = useCallback(() => {
    setOrderChanges(new Map())
    setLastSaveError(null)
  }, [])

  // Очистить ошибку
  const clearError = useCallback(() => {
    setLastSaveError(null)
  }, [])

  // Сбросить все состояния групп (полезно для отладки)
  const resetGroupStates = useCallback(() => {
    setGroupExpandedStates(new Map())
    saveExpandedStatesToStorage(new Map())
  }, [])

  return {
    orderChanges,
    hasUnsavedChanges: orderChanges.size > 0,
    changedCount: orderChanges.size,
    lastSaveError,
    isSaving,
    getTemplatesWithChanges,
    applyOrderChange,
    handleDragEnd,
    moveTemplateToGroup,
    toggleGroupExpanded,
    getGroupExpanded,
    saveOrderChanges,
    resetOrderChanges,
    clearError,
    resetGroupStates,
  }
}