import { useCallback, useEffect, useMemo, useState } from 'react'
import { useDebounce } from 'use-debounce'
import type { ApiSheet, CreateSheetInput } from '../service/sheetApiService'
import {
  useCreateSheet,
  usePatchSheet,
  useSheetsByTemplate,
} from './useSheetQueries'

export interface UseSheetAutoSaveOptions {
  templateId?: string
  autoSaveDelay?: number // задержка автосохранения в мс
  enableAutoSave?: boolean
}

export const useSheetAutoSave = (
  getAllModifiedCells: () => Record<string, Record<string, any>>,
  isCalculating: boolean,
  revision: number,
  options: UseSheetAutoSaveOptions = {}
) => {
  const { templateId, autoSaveDelay = 2000, enableAutoSave = true } = options

  // Состояние
  const [lastSavedRevision, setLastSavedRevision] = useState(0)
  const [lastSaveError, setLastSaveError] = useState<string | null>(null)

  // React Query хуки
  const {
    data: sheetsResponse,
    isLoading,
    error: loadError,
    refetch: refetchSheets,
  } = useSheetsByTemplate(templateId)

  const createSheetMutation = useCreateSheet()
  const patchSheetMutation = usePatchSheet()

  // Мемоизируем карту листов
  const sheetsMap = useMemo(() => {
    if (!sheetsResponse?.sheets) return {}

    return sheetsResponse.sheets.reduce<Record<string, ApiSheet>>(
      (acc, sheet) => {
        acc[sheet.name] = sheet
        return acc
      },
      {}
    )
  }, [sheetsResponse?.sheets])

  // Дебаунсинг ревизии для автосохранения
  const [debouncedRevision] = useDebounce(revision, autoSaveDelay)

  // Состояние сохранения
  const isSaving = createSheetMutation.isPending || patchSheetMutation.isPending

  // Обновляем ошибку при ошибках загрузки или сохранения
  useEffect(() => {
    if (loadError) {
      setLastSaveError('Ошибка загрузки листов')
    } else if (createSheetMutation.error) {
      setLastSaveError(createSheetMutation.error.message)
    } else if (patchSheetMutation.error) {
      setLastSaveError(patchSheetMutation.error.message)
    }
  }, [loadError, createSheetMutation.error, patchSheetMutation.error])

  // Основная функция сохранения через React Query
  const performSave = useCallback(
    async (data: Record<string, Record<string, any>>) => {
      if (!templateId) return

      // Получаем список всех листов, которые нужно обработать
      const dataSheetNames = Object.keys(data)
      const existingSheetNames = Object.keys(sheetsMap)
      const allSheetNames = new Set([...dataSheetNames, ...existingSheetNames])

      if (allSheetNames.size === 0) return

      setLastSaveError(null)

      try {
        // Создаем массив промисов для параллельного выполнения
        const savePromises = Array.from(allSheetNames).map(async sheetName => {
          const sheetCells = data[sheetName] || {} // если данных нет, используем пустой объект
          const existingSheet = sheetsMap[sheetName]

          if (existingSheet) {
            // Обновляем существующий лист
            await patchSheetMutation.mutateAsync({
              sheetId: existingSheet.id,
              data: { cells: sheetCells },
            })
          } else {
            // Создаем новый лист только если есть данные
            if (Object.keys(sheetCells).length > 0) {
              const createInput: CreateSheetInput = {
                name: sheetName,
                cells: sheetCells,
                template_id: templateId,
              }
              await createSheetMutation.mutateAsync(createInput)
            }
          }
        })

        await Promise.all(savePromises)
        setLastSavedRevision(revision)
      } catch (error) {
        const errorMessage =
          error instanceof Error ? error.message : 'Неизвестная ошибка'
        setLastSaveError(errorMessage)
        console.error('❌ Ошибка при сохранении листов:', errorMessage)
      }
    },
    [templateId, sheetsMap, revision, createSheetMutation, patchSheetMutation]
  )

  // Автосохранение при изменении дебаунсированной ревизии
  useEffect(() => {
    const shouldAutoSave =
      enableAutoSave &&
      debouncedRevision > lastSavedRevision &&
      !isCalculating &&
      !isSaving &&
      templateId

    if (shouldAutoSave) {
      if (process.env.NODE_ENV !== 'production') {
        console.log(
          '✅ Выполняем автосохранение для ревизии:',
          debouncedRevision
        )
      }
      const diff = getAllModifiedCells()
      if (Object.keys(diff).length > 0) {
        performSave(diff)
      }
    }
  }, [
    enableAutoSave,
    debouncedRevision,
    lastSavedRevision,
    isCalculating,
    isSaving,
    templateId,
    getAllModifiedCells,
    performSave,
  ])

  // Ручное сохранение
  const manualSave = useCallback(() => {
    const currentData = getAllModifiedCells()
    if (Object.keys(currentData).length > 0) {
      performSave(currentData)
    }
  }, [getAllModifiedCells, performSave])

  // Функция загрузки сохраненных листов (теперь используем React Query кеш)
  const loadSavedSheets = useCallback((): Record<
    string,
    Record<string, any>
  > => {
    const result: Record<string, Record<string, any>> = {}

    Object.entries(sheetsMap).forEach(([sheetName, sheet]) => {
      if (sheet.cells && Object.keys(sheet.cells).length > 0) {
        result[sheetName] = sheet.cells
      }
    })

    return result
  }, [sheetsMap])

  // Функция загрузки листов (используем refetch из React Query)
  const loadSheets = useCallback(async () => {
    const result = await refetchSheets()
    return (
      result.data?.sheets.reduce<Record<string, ApiSheet>>((acc, sheet) => {
        acc[sheet.name] = sheet
        return acc
      }, {}) || {}
    )
  }, [refetchSheets])

  // Вычисляемые значения
  const isDataChanged = revision > lastSavedRevision
  const hasUnsavedChanges = isDataChanged && !isSaving

  return {
    // Состояние
    isSaving,
    isLoading,
    isDataChanged,
    hasUnsavedChanges,
    lastSaveError,
    lastSavedRevision,
    sheets: sheetsMap,

    // Методы
    manualSave,
    loadSavedSheets,
    loadSheets,

    // Утилиты
    getCurrentData: getAllModifiedCells,
    clearError: () => setLastSaveError(null),
  }
}
