'use client'

import { useState, useCallback, useEffect, useRef } from 'react'

interface RouteParams {
  [key: string]: string
}

function stripBase(pathname: string, basePath: string): string {
  if (pathname.startsWith(basePath)) {
    const rest = pathname.slice(basePath.length)
    return rest === '' || rest === '/' ? '/' : rest.startsWith('/') ? rest : `/${rest}`
  }
  return '/'
}

export function useAdminRouter(basePath = '/admin', serverPath = '/') {
  const [currentPath, setCurrentPath] = useState(serverPath)
  const baseRef = useRef(basePath)
  baseRef.current = basePath

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const browserPath = stripBase(window.location.pathname, basePath)
      if (browserPath !== currentPath) {
        setCurrentPath(browserPath)
      }
    }
  }, []) // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    function onPopState() {
      setCurrentPath(stripBase(window.location.pathname, baseRef.current))
    }
    window.addEventListener('popstate', onPopState)
    return () => window.removeEventListener('popstate', onPopState)
  }, [])

  const navigate = useCallback((path: string) => {
    const normalizedPath = path.startsWith('/') ? path : `/${path}`
    setCurrentPath(normalizedPath)

    const fullUrl = normalizedPath === '/' ? baseRef.current : `${baseRef.current}${normalizedPath}`
    // `__NA: true` marks this as a native history entry so Next.js 16's patched
    // `history.pushState` short-circuits to the original implementation instead
    // of running its URL-parsing path (which throws "Invalid URL"). The admin is
    // a self-contained SPA with its own `popstate` listener, so we deliberately
    // bypass Next's router/RSC sync on in-admin navigation.
    window.history.pushState({ adminPath: normalizedPath, __NA: true }, '', fullUrl)
  }, [])

  // Build an absolute (basePath-prefixed) admin URL without navigating. Used
  // for links that must load a real document — e.g. opening a preview in a
  // new browser tab, where `pushState` (which only mutates the current tab)
  // is not an option.
  const buildHref = useCallback((path: string) => {
    const normalizedPath = path.startsWith('/') ? path : `/${path}`
    return normalizedPath === '/' ? baseRef.current : `${baseRef.current}${normalizedPath}`
  }, [])

  const matchRoute = useCallback(
    (pattern: string): RouteParams | null => {
      // Match against the path only — query string / hash are state-bearing
      // (e.g. `/seo?tab=audit`) and must not defeat route matching.
      const pathname = currentPath.split('?')[0]!.split('#')[0]!
      const patternParts = pattern.split('/').filter(Boolean)
      const pathParts = pathname.split('/').filter(Boolean)

      if (pattern === '/' && pathParts.length === 0) {
        return {}
      }

      if (patternParts.length !== pathParts.length) {
        return null
      }

      const params: RouteParams = {}

      for (let i = 0; i < patternParts.length; i++) {
        const patternPart = patternParts[i]!
        const pathPart = pathParts[i]!

        if (patternPart.startsWith(':')) {
          params[patternPart.slice(1)] = pathPart
        } else if (patternPart !== pathPart) {
          return null
        }
      }

      return params
    },
    [currentPath],
  )

  return { currentPath, navigate, matchRoute, buildHref }
}
