"use client"

import type React from "react"
import { createContext, useContext, useState, useCallback, useEffect } from "react"
import type { FamilyMember, FamilyTreeData } from "@/types/family"
import { mockFamilyData } from "@/lib/mock-data"
import { db } from "@/lib/db"
import { useLiveQuery } from "dexie-react-hooks"

interface FamilyContextType {
  treeData: FamilyTreeData
  getMember: (id: string) => FamilyMember | undefined
  addMember: (member: FamilyMember) => Promise<void>
  updateMember: (id: string, updates: Partial<FamilyMember>) => Promise<void>
  deleteMember: (id: string) => Promise<void>
  searchResults: FamilyMember[]
  searchMembers: (query: string) => void
  loadData: (data: FamilyTreeData) => Promise<void>
  resetData: () => Promise<void>
  isLoading: boolean
}

const FamilyContext = createContext<FamilyContextType | undefined>(undefined)

export function FamilyProvider({ children }: { children: React.ReactNode }) {
  const [searchResults, setSearchResults] = useState<FamilyMember[]>([])
  const [isInitialized, setIsInitialized] = useState(false)

  // Live query to get all members
  const members = useLiveQuery(() => db.members.toArray())
  // Live query to get rootId
  const rootIdSetting = useLiveQuery(() => db.settings.get("rootId"))

  // Initialize DB with mock data if empty
  useEffect(() => {
    const initDb = async () => {
      const count = await db.members.count()
      if (count === 0) {
        await db.transaction("rw", db.members, db.settings, async () => {
          await db.members.bulkAdd(Object.values(mockFamilyData.members))
          await db.settings.put({ key: "rootId", value: mockFamilyData.rootId })
        })
      }
      setIsInitialized(true)
    }
    initDb()
  }, [])

  // Construct treeData from DB results
  const treeData: FamilyTreeData = {
    rootId: rootIdSetting?.value || "",
    members: (members || []).reduce(
      (acc, member) => {
        acc[member.id] = member
        return acc
      },
      {} as Record<string, FamilyMember>,
    ),
  }

  const getMember = useCallback(
    (id: string) => {
      return treeData.members[id]
    },
    [treeData],
  )

  const addMember = useCallback(async (member: FamilyMember) => {
    await db.transaction("rw", db.members, async () => {
      // Add the member
      await db.members.add(member)

      // Update relationships (Father)
      if (member.fatherId) {
        const father = await db.members.get(member.fatherId)
        if (father && !father.childrenIds.includes(member.id)) {
          await db.members.update(member.fatherId, {
            childrenIds: [...father.childrenIds, member.id],
          })
        }
      }

      // Update relationships (Mother)
      if (member.motherId) {
        const mother = await db.members.get(member.motherId)
        if (mother && !mother.childrenIds.includes(member.id)) {
          await db.members.update(member.motherId, {
            childrenIds: [...mother.childrenIds, member.id],
          })
        }
      }

      // Update relationships (Spouses)
      if (member.spouseIds && member.spouseIds.length > 0) {
        for (const spouseId of member.spouseIds) {
          const spouse = await db.members.get(spouseId)
          if (spouse && !spouse.spouseIds.includes(member.id)) {
            await db.members.update(spouseId, {
              spouseIds: [...spouse.spouseIds, member.id],
            })
          }
        }
      }
    })
  }, [])

  const updateMember = useCallback(async (id: string, updates: Partial<FamilyMember>) => {
    await db.members.update(id, {
      ...updates,
      updatedAt: new Date().toISOString(),
    })
  }, [])

  const deleteMember = useCallback(async (id: string) => {
    await db.transaction("rw", db.members, db.settings, async () => {
      // Remove from DB
      await db.members.delete(id)

      // Note: In a real app, we should also remove references to this ID from other members'
      // childrenIds, spouseIds, etc. For now, we'll keep it simple as per the original implementation.

      // If we deleted the root, we might want to handle that, but for now let's leave it.
    })
  }, [])

  const loadData = useCallback(async (data: FamilyTreeData) => {
    await db.transaction("rw", db.members, db.settings, async () => {
      await db.members.clear()
      await db.members.bulkAdd(Object.values(data.members))
      await db.settings.put({ key: "rootId", value: data.rootId })
    })
  }, [])

  const resetData = useCallback(async () => {
    await loadData(mockFamilyData)
  }, [loadData])

  const searchMembers = useCallback(
    (query: string) => {
      if (!query.trim()) {
        setSearchResults([])
        return
      }

      const lowerQuery = query.toLowerCase()
      // Perform search on the in-memory treeData for simplicity and speed
      // (Dexie also supports querying, but we already have the data loaded)
      const results = Object.values(treeData.members).filter(
        (member) =>
          member.fullName.includes(lowerQuery) ||
          member.givenName.includes(lowerQuery) ||
          member.courtesyName?.includes(lowerQuery) ||
          member.artName?.includes(lowerQuery),
      )
      setSearchResults(results)
    },
    [treeData],
  )

  // Listen for import events (legacy support for the file input in settings if needed, 
  // but we should prefer using the context method)
  useEffect(() => {
    const handleImport = (e: CustomEvent<FamilyTreeData>) => {
      loadData(e.detail)
    }
    window.addEventListener("family-data-import" as any, handleImport as any)
    return () => window.removeEventListener("family-data-import" as any, handleImport as any)
  }, [loadData])

  return (
    <FamilyContext.Provider
      value={{
        treeData,
        getMember,
        addMember,
        updateMember,
        deleteMember,
        searchResults,
        searchMembers,
        loadData,
        resetData,
        isLoading: !isInitialized || !members,
      }}
    >
      {children}
    </FamilyContext.Provider>
  )
}

export function useFamily() {
  const context = useContext(FamilyContext)
  if (context === undefined) {
    throw new Error("useFamily must be used within a FamilyProvider")
  }
  return context
}
