'use client'

import { createContext, useContext, useState, useEffect, ReactNode } from 'react'
import { LabelColorName, LABEL_COLORS } from '@/lib/types'
import { getHashColor } from '@/lib/utils'

export interface Label {
  id: string
  name: string
  color: LabelColorName
  userId?: string | null
  createdAt: Date
  updatedAt: Date
}

interface LabelContextType {
  labels: Label[]
  loading: boolean
  notebookId?: string | null
  setNotebookId: (notebookId: string | null) => void
  addLabel: (name: string, color?: LabelColorName, notebookId?: string | null) => Promise<void>
  updateLabel: (id: string, updates: Partial<Pick<Label, 'name' | 'color'>>) => Promise<void>
  deleteLabel: (id: string) => Promise<void>
  getLabelColor: (name: string) => LabelColorName
  refreshLabels: () => Promise<void>
}

const LabelContext = createContext<LabelContextType | undefined>(undefined)

export function LabelProvider({ children }: { children: ReactNode }) {
  const [labels, setLabels] = useState<Label[]>([])
  const [loading, setLoading] = useState(true)
  const [notebookId, setNotebookId] = useState<string | null>(null)

  const fetchLabels = async () => {
    try {
      setLoading(true)
      // Build URL with notebookId filter
      const url = new URL('/api/labels', window.location.origin)
      if (notebookId) {
        url.searchParams.set('notebookId', notebookId)
      }

      const response = await fetch(url.toString(), {
        cache: 'no-store',
        credentials: 'include'
      })
      const data = await response.json()
      if (data.success && data.data) {
        setLabels(data.data)
      }
    } catch (error) {
      console.error('Failed to fetch labels:', error)
    } finally {
      setLoading(false)
    }
  }

  // Re-fetch labels when notebookId changes
  useEffect(() => {
    fetchLabels()
  }, [notebookId])

  const addLabel = async (name: string, color?: LabelColorName, labelNotebookId?: string | null) => {
    try {
      const labelColor = color || getHashColor(name);
      const finalNotebookId = labelNotebookId || notebookId

      const response = await fetch('/api/labels', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name, color: labelColor, notebookId: finalNotebookId }),
      })
      const data = await response.json()
      if (data.success && data.data) {
        setLabels(prev => [...prev, data.data])
      }
    } catch (error) {
      console.error('Failed to add label:', error)
      throw error
    }
  }

  const updateLabel = async (id: string, updates: Partial<Pick<Label, 'name' | 'color'>>) => {
    try {
      const response = await fetch(`/api/labels/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updates),
      })
      const data = await response.json()
      if (data.success && data.data) {
        setLabels(prev => prev.map(label => 
          label.id === id ? { ...label, ...data.data } : label
        ))
      }
    } catch (error) {
      console.error('Failed to update label:', error)
      throw error
    }
  }

  const deleteLabel = async (id: string) => {
    try {
      const response = await fetch(`/api/labels/${id}`, {
        method: 'DELETE',
      })
      if (response.ok) {
        setLabels(prev => prev.filter(label => label.id !== id))
      }
    } catch (error) {
      console.error('Failed to delete label:', error)
      throw error
    }
  }

  const getLabelColorHelper = (name: string): LabelColorName => {
    const label = labels.find(l => l.name.toLowerCase() === name.toLowerCase())
    return label?.color || 'gray'
  }

  const refreshLabels = async () => {
    await fetchLabels()
  }

  const value: LabelContextType = {
    labels,
    loading,
    notebookId,
    setNotebookId,
    addLabel,
    updateLabel,
    deleteLabel,
    getLabelColor: getLabelColorHelper,
    refreshLabels,
  }

  return <LabelContext.Provider value={value}>{children}</LabelContext.Provider>
}

export function useLabels() {
  const context = useContext(LabelContext)
  if (context === undefined) {
    throw new Error('useLabels must be used within a LabelProvider')
  }
  return context
}