import { ConfigProvider, Result, Spin, theme } from 'antd'
import { useCallback, useMemo } from 'react'
import './App.css'
import {
  buildKeycloakAuthorizationUrl,
  getKeycloakClientConfig,
  authenticatedFetch,
  logout,
  oidcStateStorageKey,
  submitKeycloakLogout,
  storeAuthTokenSet,
} from './auth/authContracts'
import { useOidcSession } from './auth/useOidcSession'
import { WorkspaceShell } from './workspace/WorkspaceShell'
import { workspaceThemeTokens } from './workspace/workspaceContracts'

function App() {
  const session = useOidcSession()
  const config = useMemo(() => getKeycloakClientConfig(), [])

  const handleLogout = useCallback(async () => {
    const idToken = session.status === 'authenticated' ? (session.tokens.idToken ?? '') : ''
    const accessToken = session.status === 'authenticated' ? session.tokens.accessToken : undefined
    await logout(idToken, accessToken)
    const state = crypto.randomUUID()
    window.sessionStorage.setItem(oidcStateStorageKey, state)
    if (idToken) {
      submitKeycloakLogout(config, idToken, window.location.origin)
      return
    }

    window.location.assign(
      buildKeycloakAuthorizationUrl(config, state, crypto.randomUUID()).toString(),
    )
  }, [session, config])

  const adminFetch = useCallback(
    async (input: RequestInfo | URL, init: RequestInit = {}) => {
      if (session.status !== 'authenticated') {
        throw new Error('Admin request requires an authenticated session')
      }

      return authenticatedFetch(input, init, config, session.tokens, storeAuthTokenSet)
    },
    [config, session],
  )

  const content =
    session.status === 'authenticated' ? (
      <WorkspaceShell user={session.user} onLogout={handleLogout} adminFetch={adminFetch} />
    ) : session.status === 'error' ? (
      <Result status="warning" title={session.error} />
    ) : (
      <div className="app-auth-state" aria-live="polite">
        <Spin />
      </div>
    )

  return (
    <ConfigProvider
      theme={{
        algorithm: theme.compactAlgorithm,
        token: workspaceThemeTokens,
        components: {
          Layout: {
            headerBg: '#FFFFFF',
            siderBg: '#FFFFFF',
          },
          Table: {
            cellPaddingBlockSM: 6,
            cellPaddingInlineSM: 8,
          },
        },
      }}
    >
      <div className="app-shell">
        {content}
      </div>
    </ConfigProvider>
  )
}

export default App
