"use client"

import { getUserOrganizations } from "@/components/dashboard/action"
import { setOrgCookie } from "./org-cookie-action"
import type { User as UserProfile } from "@auth0/nextjs-auth0/types"
import { useRouter } from "next/navigation"
import React, {
  createContext,
  useContext,
  useEffect,
  useState,
  useMemo,
  useRef,
  useCallback,
} from "react"

export type ViewMode = "personal" | "organization"

type ViewModeContextType = {
  mode: ViewMode
  currentOrg?: Organization | null
  orgs: Organization[]
  loading: boolean
  switchToMode: (mode: ViewMode, orgId?: string) => Promise<void>
}

const ViewModeContext = createContext<ViewModeContextType>({
  loading: true,
  mode: "personal",
  currentOrg: undefined,
  orgs: [],
  switchToMode: async () => Promise.resolve(),
})

interface Organization {
  id: string
  name: string
  role: "admin" | "owner" | "member"
  avatarUrl?: string
}

export function ViewModeProvider({
  children,
  user,
  initialOrganizations,
  serverOrgId,
}: {
  children: React.ReactNode
  user?: UserProfile
  initialOrganizations?: Organization[]
  serverOrgId?: string | null
}) {
  const router = useRouter()
  const [mode, setMode] = useState<ViewMode>("personal")
  const [loading, setIsLoading] = useState<boolean>(!initialOrganizations)
  const [orgs, setOrgs] = useState<Organization[]>(initialOrganizations ?? [])
  const [currentOrg, setCurrentOrg] = useState<Organization | null>(null)
  const fetchingRef = useRef(false)
  const orgsRef = useRef<Organization[]>(initialOrganizations ?? [])

  const setLocalStorageMode = useCallback((newMode: ViewMode, orgId?: string) => {
    localStorage.setItem("viewMode", newMode)
    if (newMode === "organization" && orgId) {
      localStorage.setItem("currentOrganizationId", orgId)
    } else {
      localStorage.removeItem("currentOrganizationId")
    }
  }, [])

  const switchToMode = useCallback(
    async (newMode: ViewMode, orgId?: string, fetchedOrgs?: Organization[]) => {
      if (!user?.sub) return

      const finalOrgs = fetchedOrgs || orgsRef.current
      setLocalStorageMode(newMode, orgId)

      // Sync org cookie so server components can read it
      const cookieOrgId = newMode === "organization" && orgId ? orgId : null
      await setOrgCookie(cookieOrgId)

      if (newMode === "organization" && orgId) {
        const org = finalOrgs.find(o => o.id === orgId)
        if (org) {
          setMode("organization")
          setCurrentOrg(org)
        } else {
          setMode("personal")
          setCurrentOrg(null)
        }
      } else {
        setMode("personal")
        setCurrentOrg(null)
      }

      // Trigger server re-render so server components pick up the new cookie
      router.refresh()
    },
    [user?.sub, setLocalStorageMode, router],
  )

  useEffect(() => {
    if (!user?.sub) {
      setIsLoading(false)
      return
    }

    // If initial data was provided by the server, restore state locally
    // and only sync cookie + refresh if localStorage disagrees with the server cookie
    if (initialOrganizations) {
      const savedMode = localStorage.getItem("viewMode") as ViewMode
      const savedOrgId = localStorage.getItem("currentOrganizationId")

      if (savedMode === "organization" && savedOrgId) {
        const org = initialOrganizations.find(o => o.id === savedOrgId)
        if (org) {
          setMode("organization")
          setCurrentOrg(org)
          setLocalStorageMode("organization", savedOrgId)

          // Only sync cookie if server doesn't match
          if (serverOrgId !== savedOrgId) {
            setOrgCookie(savedOrgId).then(() => router.refresh())
          }
        } else {
          // Saved org not found in orgs list — fall back to personal
          setMode("personal")
          setCurrentOrg(null)
          setLocalStorageMode("personal")
          if (serverOrgId) {
            setOrgCookie(null).then(() => router.refresh())
          }
        }
      } else {
        // Personal mode — defaults are already correct
        setMode("personal")
        setCurrentOrg(null)
        setLocalStorageMode("personal")

        // Only sync cookie if server still has an org cookie
        if (serverOrgId) {
          setOrgCookie(null).then(() => router.refresh())
        }
      }

      setIsLoading(false)
      return
    }

    // Fallback: no server data, fetch client-side
    if (fetchingRef.current) return
    fetchingRef.current = true

    setIsLoading(true)
    getUserOrganizations(user.sub)
      .then(result => {
        if (result.success && result.organizations) {
          setOrgs(result.organizations)
          orgsRef.current = result.organizations
          const savedMode = localStorage.getItem("viewMode") as ViewMode
          const savedOrgId = localStorage.getItem("currentOrganizationId")
          if (savedMode === "organization" && savedOrgId) {
            switchToMode("organization", savedOrgId, result.organizations)
          } else {
            switchToMode("personal", undefined, result.organizations)
          }
        }
      })
      .catch(error => console.error("Error fetching organizations:", error))
      .finally(() => {
        setIsLoading(false)
        fetchingRef.current = false
      })
  }, [user?.sub, initialOrganizations, serverOrgId, setLocalStorageMode, switchToMode, router])

  const contextValue = useMemo(
    () => ({ mode, orgs, loading, currentOrg, switchToMode }),
    [mode, orgs, loading, currentOrg, switchToMode],
  )

  return <ViewModeContext.Provider value={contextValue}>{children}</ViewModeContext.Provider>
}

export function useViewMode() {
  const context = useContext(ViewModeContext)
  if (!context) {
    throw new Error("useViewMode must be used within a ViewModeProvider")
  }
  return context
}
