"use client"

import { useEffect, useRef, useState, type ReactNode } from "react"
import { usePathname } from "next/navigation"
import { isAuthPublicPath } from "@/lib/auth/public-paths"
import { ensureNativeAccessToken } from "@/lib/auth/native-session"
import { hydrateNativeRuntimeConfig } from "@/lib/runtime-config/native"
import { getRuntimeConfig } from "@/lib/runtime-config"
import { useNativeRuntime } from "@/lib/platform"
import { NativeLogin } from "@/components/mobile/native-login"
import { ServerPicker } from "@/components/mobile/server-picker"

function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
  return Promise.race([
    promise,
    new Promise<T>((_, reject) => {
      setTimeout(() => reject(new Error("timeout")), ms)
    }),
  ])
}

type AuthScreen = "picker" | "login" | "none"

function initialAuthScreen(pathname: string): AuthScreen {
  if (isAuthPublicPath(pathname)) return "none"
  // SSR-safe: never read localStorage here (hydration mismatch breaks touch on Android).
  return "picker"
}

function NativeAuthScreen({ children }: { children: ReactNode }) {
  return (
    <div className="native-auth-screen fixed inset-0 z-[10000] flex h-dvh flex-col overflow-auto bg-background touch-manipulation">
      {children}
    </div>
  )
}

/**
 * On native shells, show server picker / login inline (no client router redirects).
 */
export function NativeAuthGate({ children }: { children: ReactNode }) {
  const native = useNativeRuntime()
  const pathname = usePathname()
  const booted = useRef(false)
  const [authScreen, setAuthScreen] = useState<AuthScreen>(() =>
    native ? initialAuthScreen(pathname) : "none"
  )
  const [returnTo, setReturnTo] = useState("/mail/inbox")

  useEffect(() => {
    if (!native) return

    const dest = pathname.startsWith("/") ? pathname : "/mail/inbox"
    setReturnTo(dest)

    if (isAuthPublicPath(pathname)) {
      setAuthScreen("none")
    }
  }, [native, pathname])

  useEffect(() => {
    if (!native || booted.current) return

    let cancelled = false

    async function bootstrap() {
      try {
        await withTimeout(hydrateNativeRuntimeConfig(), 3_000)
      } catch {
        /* localStorage fallback */
      }

      if (cancelled) return

      if (isAuthPublicPath(pathname)) {
        setAuthScreen("none")
        return
      }

      if (!getRuntimeConfig()) {
        setAuthScreen("picker")
        return
      }

      let token: string | null = null
      try {
        token = await withTimeout(ensureNativeAccessToken(), 8_000)
      } catch {
        token = null
      }

      if (cancelled) return
      setAuthScreen(token ? "none" : "login")
    }

    void bootstrap().finally(() => {
      if (!cancelled) booted.current = true
    })

    return () => {
      cancelled = true
    }
  }, [native, pathname])

  if (!native) return children

  if (isAuthPublicPath(pathname) || authScreen === "none") {
    return children
  }

  if (authScreen === "picker") {
    return (
      <NativeAuthScreen>
        <ServerPicker
          onSelected={() => {
            setAuthScreen("login")
          }}
        />
      </NativeAuthScreen>
    )
  }

  return (
    <NativeAuthScreen>
      <NativeLogin returnTo={returnTo} />
    </NativeAuthScreen>
  )
}
