import { Modal } from '../layouts/modal'
import { CreatePage } from '../pages/create'
import { HomePage } from '../pages/home'
import { LandingPage } from '../pages/landing'
import { Login } from '../pages/login'
import { Nostr } from '../pages/nostr'
import { ProfilePage } from '../pages/profile'
import { Register } from '../pages/register'
import { SettingsPage } from '../pages/settings/Settings'
import { CacheSettingsPage } from '../pages/settings/cache'
import { ProfileSettingsPage } from '../pages/settings/profile'
import { RelaysPage } from '../pages/settings/relays'
import { SignPage } from '../pages/sign'
import { VerifyPage } from '../pages/verify'
import { hexToNpub } from '../utils'
import { Route, RouteProps } from 'react-router-dom'

export const appPrivateRoutes = {
  homePage: '/',
  create: '/create',
  sign: '/sign',
  settings: '/settings',
  profileSettings: '/settings/profile/:npub',
  cacheSettings: '/settings/cache',
  relays: '/settings/relays'
}

export const appPublicRoutes = {
  profile: '/profile/:npub',
  landingPage: '/',
  login: '/login',
  register: '/login/register',
  nostr: '/login/nostr',
  verify: '/verify',
  source: 'https://git.sigit.io/sig/it',
  docs: 'https://docs.sigit.io'
}

export const getProfileRoute = (hexKey: string) =>
  appPublicRoutes.profile.replace(':npub', hexToNpub(hexKey))

export const getProfileSettingsRoute = (hexKey: string) =>
  appPrivateRoutes.profileSettings.replace(':npub', hexToNpub(hexKey))

/**
 * Helper type allows for extending react-router-dom's **RouteProps** with generic type
 */
type CustomRouteProps<T> = T &
  Omit<RouteProps, 'children'> & {
    children?: Array<CustomRouteProps<T>>
  }

/**
 *  This function maps over nested routes with optional condition for rendering
 *  @param {CustomRouteProps<T>[]} routes - routes list
 *  @param {RenderConditionCallbackFn} renderConditionCallbackFn - render condition callback (default true)
 */
export function recursiveRouteRenderer<T>(
  routes?: CustomRouteProps<T>[],
  renderConditionCallbackFn: (route: CustomRouteProps<T>) => boolean = () =>
    true
) {
  if (!routes) return null

  // Callback allows us to pass arbitrary conditions for each route's rendering
  // Skipping the callback will by default evaluate to true (show route)
  return routes.map((route, index) =>
    renderConditionCallbackFn(route) ? (
      <Route
        key={`${route.path}${index}`}
        path={route.path}
        element={route.element}
      >
        {recursiveRouteRenderer(route.children, renderConditionCallbackFn)}
      </Route>
    ) : null
  )
}

type PublicRouteProps = CustomRouteProps<{
  hiddenWhenLoggedIn?: boolean
}>

export const publicRoutes: PublicRouteProps[] = [
  {
    path: appPublicRoutes.landingPage,
    hiddenWhenLoggedIn: true,
    element: <LandingPage />,
    children: [
      {
        element: <Modal />,
        children: [
          {
            path: appPublicRoutes.login,
            hiddenWhenLoggedIn: true,
            element: <Login />
          },
          {
            path: appPublicRoutes.register,
            hiddenWhenLoggedIn: true,
            element: <Register />
          },
          {
            path: appPublicRoutes.nostr,
            hiddenWhenLoggedIn: true,
            element: <Nostr />
          }
        ]
      }
    ]
  },
  {
    path: appPublicRoutes.profile,
    element: <ProfilePage />
  },
  {
    path: appPublicRoutes.verify,
    element: <VerifyPage />
  }
]

export const privateRoutes = [
  {
    path: appPrivateRoutes.homePage,
    element: <HomePage />
  },
  {
    path: appPrivateRoutes.create,
    element: <CreatePage />
  },
  {
    path: appPrivateRoutes.sign,
    element: <SignPage />
  },
  {
    path: appPrivateRoutes.settings,
    element: <SettingsPage />
  },
  {
    path: appPrivateRoutes.profileSettings,
    element: <ProfileSettingsPage />
  },
  {
    path: appPrivateRoutes.cacheSettings,
    element: <CacheSettingsPage />
  },
  {
    path: appPrivateRoutes.relays,
    element: <RelaysPage />
  }
]
