// hooks/use-table-presets.ts
import { TableSettings } from "@/db/schema"
import { useSession } from "next-auth/react"
import { useCallback, useEffect, useState } from "react"
import { toast } from "sonner"
import useSWR from "swr"
import { useSearchParams } from "next/navigation"

interface TablePreset {
  id: string
  userId: string
  tableId: string
  name: string
  settings: TableSettings
  isDefault: boolean
  isActive: boolean
  isShared: boolean
  createdAt: Date
  updatedAt: Date
}

export function useTablePresets<TData>(
  tableId: string,
  initialSettings: TableSettings<TData>
) {
  const { data: session } = useSession()
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
  const [isClient, setIsClient] = useState(false)
  const searchParams = useSearchParams()
  
  // 클라이언트 마운트 확인
  useEffect(() => {
    setIsClient(true)
  }, [])
  
  // SWR을 사용한 데이터 페칭
  const {
    data: presets,
    error,
    mutate,
    isLoading
  } = useSWR<TablePreset[]>(
    session?.user ? `/api/table-presets?tableId=${tableId}` : null,
    (url: string) => fetch(url).then(res => res.json()),
    {
      revalidateOnFocus: false,
      revalidateOnReconnect: true,
    }
  )

  const activePreset = presets?.find(p => p.isActive)
  
  // 현재 설정 가져오기 (URL + 활성 프리셋의 클라이언트 상태)
  const getCurrentSettings = useCallback((): TableSettings<TData> => {
    // 서버 렌더링 중이면 initialSettings 사용
    if (!isClient || typeof window === 'undefined') {
      return initialSettings
    }
    
    // 클라이언트에서만 URL 파라미터 읽기
    const urlSettings = {
      page: parseInt(searchParams.get('page') || '1'),
      perPage: parseInt(searchParams.get('perPage') || '10'),
      sort: JSON.parse(searchParams.get('sort') || JSON.stringify(initialSettings.sort)),
      filters: JSON.parse(searchParams.get('filters') || '[]'),
      joinOperator: (searchParams.get('joinOperator') as "and" | "or") || "and",
      basicFilters: JSON.parse(searchParams.get('basicFilters') || '[]'),
      basicJoinOperator: (searchParams.get('basicJoinOperator') as "and" | "or") || "and",
      search: searchParams.get('search') || '',
      from: searchParams.get('from') || undefined,
      to: searchParams.get('to') || undefined,
    }
    
    // 활성 프리셋의 클라이언트 설정 병합
    if (activePreset) {
      return {
        ...urlSettings,
        columnVisibility: activePreset.settings.columnVisibility || {},
        columnOrder: activePreset.settings.columnOrder || [],
        pinnedColumns: activePreset.settings.pinnedColumns || { left: [], right: [] },
        groupBy: activePreset.settings.groupBy || [],
        expandedRows: activePreset.settings.expandedRows || []
      }
    }
    
    return urlSettings
  }, [activePreset, initialSettings, isClient, searchParams])

  // 프리셋 생성
  const createPreset = useCallback(async (
    name: string,
    settings: TableSettings<TData>,
    isDefault = false
  ) => {
    try {
      const response = await fetch('/api/table-presets', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          tableId,
          name,
          settings,
          isDefault
        })
      })

      if (!response.ok) {
        throw new Error('Failed to create preset')
      }

      await mutate()
      toast.success(`프리셋 '${name}'이 저장되었습니다`)
      return true
    } catch (error) {
      console.error('Error creating preset:', error)
      toast.error('프리셋 저장 중 오류가 발생했습니다')
      return false
    }
  }, [tableId, mutate])

  // 프리셋 적용
  const applyPreset = useCallback(async (presetId: string) => {
    try {
      // 이전 활성 프리셋 비활성화 (있는 경우)
      if (activePreset && activePreset.id !== presetId) {
        await fetch(`/api/table-presets/${activePreset.id}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ isActive: false })
        })
      }

      // 새 프리셋 활성화
      await fetch(`/api/table-presets/${presetId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ isActive: true })
      })

      const preset = presets?.find(p => p.id === presetId)
      if (!preset) return false

      // 클라이언트에서만 URL 업데이트
      if (isClient && typeof window !== 'undefined') {
        const params = new URLSearchParams()
        if (preset.settings.page !== 1) params.set('page', preset.settings.page.toString())
        if (preset.settings.perPage !== 10) params.set('perPage', preset.settings.perPage.toString())
        if (preset.settings.sort && preset.settings.sort.length > 0) params.set('sort', JSON.stringify(preset.settings.sort))
        if (preset.settings.filters && preset.settings.filters.length > 0) params.set('filters', JSON.stringify(preset.settings.filters))
        if (preset.settings.joinOperator !== 'and') params.set('joinOperator', preset.settings.joinOperator)
        if (preset.settings.basicFilters && preset.settings.basicFilters.length > 0) params.set('basicFilters', JSON.stringify(preset.settings.basicFilters))
        if (preset.settings.basicJoinOperator !== 'and') params.set('basicJoinOperator', preset.settings.basicJoinOperator)
        if (preset.settings.search) params.set('search', preset.settings.search)
        if (preset.settings.from) params.set('from', preset.settings.from)
        if (preset.settings.to) params.set('to', preset.settings.to)

        const url = window.location.pathname + '?' + params.toString()
        window.history.pushState({}, '', url)
      }
      
      await mutate()
      
      // Next.js App Router의 경우 router.push나 window.location.reload 사용
      if (isClient && typeof window !== 'undefined') {
        window.location.reload()
      }
      
      return true
    } catch (error) {
      console.error('Error applying preset:', error)
      toast.error('프리셋 적용 중 오류가 발생했습니다')
      return false
    }
  }, [activePreset, presets, mutate, isClient])

  // 프리셋 업데이트
  const updatePreset = useCallback(async (
    presetId: string,
    settings: TableSettings<TData>
  ) => {
    try {
      const response = await fetch(`/api/table-presets/${presetId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ settings })
      })

      if (!response.ok) {
        throw new Error('Failed to update preset')
      }

      await mutate()
      const preset = presets?.find(p => p.id === presetId)
      toast.success(`${preset?.name || '프리셋'}이 업데이트되었습니다`)
    } catch (error) {
      console.error('Error updating preset:', error)
      toast.error('프리셋 업데이트 중 오류가 발생했습니다')
    }
  }, [presets, mutate])

  // 프리셋 삭제
  const deletePreset = useCallback(async (presetId: string) => {
    try {
      const response = await fetch(`/api/table-presets/${presetId}`, {
        method: 'DELETE'
      })

      if (!response.ok) {
        throw new Error('Failed to delete preset')
      }

      // 삭제할 프리셋이 활성 프리셋인 경우 다른 프리셋을 활성화
      if (activePreset?.id === presetId && presets && presets.length > 1) {
        const defaultPreset = presets.find(p => p.isDefault && p.id !== presetId) || 
                            presets.find(p => p.id !== presetId)
        if (defaultPreset) {
          await applyPreset(defaultPreset.id)
          return true
        }
      }

      await mutate()
      const preset = presets?.find(p => p.id === presetId)
      toast.success(`프리셋 '${preset?.name}'이 삭제되었습니다`)
      return true
    } catch (error) {
      console.error('Error deleting preset:', error)
      toast.error('프리셋 삭제 중 오류가 발생했습니다')
      return false
    }
  }, [activePreset, presets, mutate, applyPreset])

  // 기본 프리셋 설정
  const setDefaultPreset = useCallback(async (presetId: string) => {
    try {
      // 기존 기본 프리셋 해제
      const defaultPreset = presets?.find(p => p.isDefault)
      if (defaultPreset && defaultPreset.id !== presetId) {
        await fetch(`/api/table-presets/${defaultPreset.id}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ isDefault: false })
        })
      }

      // 새 기본 프리셋 설정
      await fetch(`/api/table-presets/${presetId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ isDefault: true })
      })

      await mutate()
      toast.success('기본 프리셋이 변경되었습니다')
    } catch (error) {
      console.error('Error setting default preset:', error)
      toast.error('기본 프리셋 설정 중 오류가 발생했습니다')
    }
  }, [presets, mutate])

  // 프리셋 이름 변경
  const renamePreset = useCallback(async (presetId: string, newName: string) => {
    try {
      if (!newName.trim()) {
        toast.error('프리셋 이름을 입력해주세요')
        return false
      }

      const response = await fetch(`/api/table-presets/${presetId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: newName.trim() })
      })

      if (!response.ok) {
        const error = await response.json()
        throw new Error(error.message || 'Failed to rename preset')
      }

      await mutate()
      toast.success('프리셋 이름이 변경되었습니다')
      return true
    } catch (error) {
      console.error('Error renaming preset:', error)
      toast.error('프리셋 이름 변경 중 오류가 발생했습니다')
      return false
    }
  }, [mutate])

  // 클라이언트 상태 업데이트 (컬럼 가시성, 핀 등)
  const updateClientState = useCallback(async (newClientState: Partial<TableSettings<TData>>) => {
    if (!activePreset) return

    const updatedSettings = {
      ...activePreset.settings,
      ...newClientState
    }

    await updatePreset(activePreset.id, updatedSettings)
  }, [activePreset, updatePreset])

  // URL 변경 감지 및 미저장 변경사항 체크
  useEffect(() => {
    if (!isClient || !presets || !activePreset) return

    const currentSettings = getCurrentSettings()
    
    // 현재 URL 설정과 활성 프리셋 설정 비교
    const isSettingsChanged = 
      currentSettings.perPage !== activePreset.settings.perPage ||
      JSON.stringify(currentSettings.sort) !== JSON.stringify(activePreset.settings.sort) ||
      JSON.stringify(currentSettings.filters) !== JSON.stringify(activePreset.settings.filters) ||
      currentSettings.joinOperator !== activePreset.settings.joinOperator ||
      JSON.stringify(currentSettings.basicFilters) !== JSON.stringify(activePreset.settings.basicFilters) ||
      currentSettings.basicJoinOperator !== activePreset.settings.basicJoinOperator ||
      currentSettings.search !== activePreset.settings.search

    setHasUnsavedChanges(isSettingsChanged)
  }, [isClient, presets, activePreset, getCurrentSettings])

  return {
    // 상태
    presets: presets || [],
    activePresetId: activePreset?.id || null,
    isLoading,
    hasUnsavedChanges,
    
    // 액션
    createPreset,
    applyPreset,
    updatePreset,
    deletePreset,
    setDefaultPreset,
    renamePreset,
    updateClientState,
    getCurrentSettings,
  }
}