import UriInputField from '@/mdx-components/UriInputField';
import InlineNotification from '@/ds-components/InlineNotification';
import Steps from '@/mdx-components/Steps';
import Step from '@/mdx-components/Step';
import NpmLikeInstallation from '@/mdx-components/NpmLikeInstallation';
import CustomDomainEndpointNotice from '@/mdx-components/CustomDomainEndpointNotice';

import Checkpoint from '../../fragments/_checkpoint.md';
import RedirectUrisWeb, { defaultRedirectUri, defaultPostSignOutUri } from '../../fragments/_redirect-uris-web.mdx';

<Steps>

<Step
  title="Installation"
  subtitle="Install Logto SDK for your project"
>

<NpmLikeInstallation packageName="@logto/react" />

</Step>

<Step title="Init Logto provider">

Import and use `LogtoProvider` to provide a Logto context to your app:

<Code className="language-tsx" title="App.tsx">
    {`import { LogtoProvider, LogtoConfig } from '@logto/react';

const config: LogtoConfig = {
  endpoint: '${props.endpoint}',
  appId: '${props.app.id}',
};

const App = () => (
  <LogtoProvider config={config}>
    <YourAppContent />
  </LogtoProvider>
);`}
</Code>

<br/>

<CustomDomainEndpointNotice />

</Step>

<Step title="Configure redirect URIs">

<RedirectUrisWeb />

</Step>

<Step title="Handle redirect">

After the user signs in, Logto will redirect the user back to the redirect URI configured above. However, there are still things to do to make your application work properly.

First let's create a callback page:

```tsx title="pages/Callback/index.tsx"
import { useHandleSignInCallback } from '@logto/react';

const Callback = () => {
  const { isLoading } = useHandleSignInCallback(() => {
    // Navigate to root path when finished
  });

  // When it's working in progress
  if (isLoading) {
    return <div>Redirecting...</div>;
  }

  return null;
};
```

Then, insert the code below to create a `/callback` route which does NOT require authentication:

```tsx title="App.tsx"
// Assuming react-router
<Route path="/callback" element={<Callback />} />
```

</Step>

<Step title="Implement sign-in and sign-out">

We provide a hook `useLogto()` which can help you easily manage the authentication flow.

<InlineNotification>
  Before calling `.signIn()`, make sure you have correctly configured Redirect URI in Admin Console.
</InlineNotification>

<Code className="language-tsx" title="pages/Home/index.tsx">
    {`import { useLogto } from '@logto/react';

const Home = () => {
  const { signIn, signOut, isAuthenticated } = useLogto();

  return isAuthenticated ? (
    <button onClick={() => signOut('${props.postLogoutRedirectUris[0] || defaultRedirectUri}')}>Sign Out</button>
  ) : (
    <button onClick={() => signIn('${props.redirectUris[0] || defaultPostSignOutUri}')}>Sign In</button>
  );
};`}
</Code>

Calling `.signOut()` will clear all the Logto data in memory and localStorage if they exist.

</Step>

<Step
  title="Checkpoint: Test your application"
>

<Checkpoint />

</Step>

<Step title="Display user information">

To display the user's information, you can use the `getIdTokenClaims()` method. For example, in your Home page:

```tsx title="pages/Home/index.tsx"
import { useLogto, type IdTokenClaims } from '@logto/react';
import { useEffect, useState } from 'react';

const Home = () => {
  const { isAuthenticated, getIdTokenClaims } = useLogto();
  const [user, setUser] = useState<IdTokenClaims>();

  useEffect(() => {
    (async () => {
      if (isAuthenticated) {
        const claims = await getIdTokenClaims();
        setUser(claims);
      }
    })();
  }, [getIdTokenClaims, isAuthenticated]);

  return (
    // ...
    {isAuthenticated && user && (
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Value</th>
          </tr>
        </thead>
        <tbody>
          {Object.entries(user).map(([key, value]) => (
            <tr key={key}>
              <td>{key}</td>
              <td>{typeof value === 'string' ? value : JSON.stringify(value)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    )}
  );
}
```

</Step>

</Steps>
