import { Attribute, TemplateAttributeDetail } from '@/type/template'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import React, { createContext, ReactNode, useContext, useMemo } from 'react'

interface CategoryContextType {
  attributes: Attribute[]
  isLoading: boolean
  error: Error | null
  refetchAttributes: () => void
  addAttribute: (data: {
    name: string
    is_required: boolean
  }) => Promise<Attribute>
  updateAttribute: (attribute: Attribute) => Promise<Attribute>
  deleteAttribute: (id: string) => Promise<string>
  // Утилитарные функции для работы с атрибутами
  getRequiredAttributes: () => Attribute[]
  getOptionalAttributes: () => Attribute[]
  getAttributeById: (id: string) => Attribute | undefined
}

interface TemplateAttributesContextType {
  getTemplateAttributes: (
    templateId: string
  ) => Promise<TemplateAttributeDetail[]>
  setTemplateAttributes: (
    templateId: string,
    attributes: Array<{ attribute_id: string; value: string | null }>
  ) => Promise<
    Array<{ template_id: string; attribute_id: string; value: string | null }>
  >
}

const CategoryContext = createContext<CategoryContextType | undefined>(
  undefined
)

const TemplateAttributesContext = createContext<
  TemplateAttributesContextType | undefined
>(undefined)

// API функции для работы с атрибутами
const fetchAttributes = async (): Promise<Attribute[]> => {
  const response = await fetch('/api/attributes/')
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`)
  }
  const data = await response.json()
  return data.attributes || []
}

const createAttribute = async (attribute: {
  name: string
  is_required: boolean
}): Promise<Attribute> => {
  const response = await fetch('/api/attributes/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(attribute),
  })
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`)
  }
  const result = await response.json()

  // После создания получаем полную информацию об атрибуте
  // так как API возвращает только id
  const attributesResponse = await fetch('/api/attributes/')
  if (!attributesResponse.ok) {
    throw new Error(`HTTP error! status: ${attributesResponse.status}`)
  }
  const attributesData = await attributesResponse.json()
  const newAttribute = attributesData.attributes.find(
    (attr: Attribute) => attr.id === result.id
  )

  if (!newAttribute) {
    throw new Error('Created attribute not found')
  }

  return newAttribute
}

const updateAttribute = async (attribute: Attribute): Promise<Attribute> => {
  // Поскольку в API нет эндпоинта для обновления атрибутов,
  // возвращаем переданный атрибут как есть
  // TODO: Добавить PATCH /attributes/{id} в API
  return attribute
}

const deleteAttribute = async (id: string): Promise<string> => {
  // Поскольку в API нет эндпоинта для удаления атрибутов,
  // просто возвращаем id
  // TODO: Добавить DELETE /attributes/{id} в API
  return id
}

// API функции для работы с атрибутами шаблонов
const fetchTemplateAttributes = async (
  templateId: string
): Promise<TemplateAttributeDetail[]> => {
  const response = await fetch(`/api/templates/${templateId}/attributes`)
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`)
  }
  const data = await response.json()
  return data.attributes || []
}

const setTemplateAttributes = async (
  templateId: string,
  attributes: Array<{ attribute_id: string; value: string | null }>
): Promise<
  Array<{ template_id: string; attribute_id: string; value: string | null }>
> => {
  const response = await fetch(`/api/templates/${templateId}/attributes`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ attributes }),
  })
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`)
  }
  return response.json()
}

export const CategoryProvider: React.FC<{ children: ReactNode }> = ({
  children,
}) => {
  const client = useQueryClient()

  const {
    data: attributes = [],
    isLoading,
    error,
    refetch,
  } = useQuery<Attribute[], Error>({
    queryKey: ['attributes'],
    queryFn: fetchAttributes,
  })

  const createMutation = useMutation({
    mutationFn: createAttribute,
    onSuccess: () => {
      client.invalidateQueries({ queryKey: ['attributes'] })
    },
  })

  const updateMutation = useMutation({
    mutationFn: updateAttribute,
    onSuccess: updated => {
      client.setQueryData<Attribute[]>(
        ['attributes'],
        old => old?.map(attr => (attr.id === updated.id ? updated : attr)) ?? []
      )
    },
  })

  const deleteMutation = useMutation({
    mutationFn: deleteAttribute,
    onSuccess: deletedId => {
      client.setQueryData<Attribute[]>(
        ['attributes'],
        old => old?.filter(attr => attr.id !== deletedId) ?? []
      )
    },
  })

  // Утилитарные функции
  const getRequiredAttributes = () =>
    attributes.filter(attr => attr.is_required)

  const getOptionalAttributes = () =>
    attributes.filter(attr => !attr.is_required)

  const getAttributeById = (id: string) =>
    attributes.find(attr => attr.id === id)

  const categoryValue = useMemo(
    () => ({
      attributes,
      isLoading:
        isLoading ||
        createMutation.isPending ||
        updateMutation.isPending ||
        deleteMutation.isPending,
      error:
        error ||
        createMutation.error ||
        updateMutation.error ||
        deleteMutation.error,
      refetchAttributes: refetch,
      addAttribute: createMutation.mutateAsync,
      updateAttribute: updateMutation.mutateAsync,
      deleteAttribute: deleteMutation.mutateAsync,
      getRequiredAttributes,
      getOptionalAttributes,
      getAttributeById,
    }),
    [
      attributes,
      isLoading,
      error,
      createMutation,
      updateMutation,
      deleteMutation,
      refetch,
    ]
  )

  const templateAttributesValue = useMemo(
    () => ({
      getTemplateAttributes: fetchTemplateAttributes,
      setTemplateAttributes: setTemplateAttributes,
    }),
    []
  )

  return (
    <CategoryContext.Provider value={categoryValue}>
      <TemplateAttributesContext.Provider value={templateAttributesValue}>
        {children}
      </TemplateAttributesContext.Provider>
    </CategoryContext.Provider>
  )
}

export const useCategoryContext = (): CategoryContextType => {
  const context = useContext(CategoryContext)
  if (!context) {
    throw new Error('useCategoryContext must be used within a CategoryProvider')
  }
  return context
}

export const useTemplateAttributesContext =
  (): TemplateAttributesContextType => {
    const context = useContext(TemplateAttributesContext)
    if (!context) {
      throw new Error(
        'useTemplateAttributesContext must be used within a CategoryProvider'
      )
    }
    return context
  }

// Хук для работы с атрибутами конкретного шаблона
export const useTemplateAttributes = (templateId: string) => {
  const client = useQueryClient()
  const { getTemplateAttributes, setTemplateAttributes } =
    useTemplateAttributesContext()

  const {
    data: templateAttributes = [],
    isLoading,
    error,
    refetch,
  } = useQuery<TemplateAttributeDetail[], Error>({
    queryKey: ['templateAttributes', templateId],
    queryFn: () => getTemplateAttributes(templateId),
    enabled: !!templateId,
  })

  const setAttributesMutation = useMutation({
    mutationFn: (
      attributes: Array<{ attribute_id: string; value: string | null }>
    ) => setTemplateAttributes(templateId, attributes),
    onSuccess: () => {
      client.invalidateQueries({ queryKey: ['templateAttributes', templateId] })
    },
  })

  return {
    templateAttributes,
    isLoading: isLoading || setAttributesMutation.isPending,
    error: error || setAttributesMutation.error,
    refetch,
    setAttributes: setAttributesMutation.mutateAsync,
  }
}

// Для обратной совместимости
export const useCategoryFields = useCategoryContext

export default CategoryProvider
