import UriInputField from '@/mdx-components/UriInputField';
import Tabs from '@/mdx-components/Tabs';
import TabItem from '@/mdx-components/TabItem';
import InlineNotification from '@/ds-components/InlineNotification';
import Steps from '@/mdx-components/Steps';
import Step from '@/mdx-components/Step';
import CustomDomainEndpointNotice from '@/mdx-components/CustomDomainEndpointNotice';
import Checkpoint from '../../fragments/_checkpoint.md';
import RedirectUrisNative, { defaultRedirectUri } from '../../fragments/_redirect-uris-native.mdx';

<Steps>

<Step
  title="Integrate Logto Swift SDK"
  subtitle="Add Logto SDK as a dependency"
>

Use the following URL to add Logto SDK as a dependency in Swift Package Manager.

```bash
https://github.com/logto-io/swift.git
```

Since Xcode 11, you can [directly import a swift package](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app) w/o any additional tool.

We do not support **Carthage** and **CocoaPods** at the time due to some technical issues.

<Details>
  <summary>Carthage</summary>

Carthage [needs a `xcodeproj` file to build](https://github.com/Carthage/Carthage/issues/1226#issuecomment-290931385), but `swift package generate-xcodeproj` will report a failure since we are using binary targets
for native social plugins. We will try to find a workaround later.

</Details>

<Details>
  <summary>CocoaPods</summary>

CocoaPods [does not support local dependency](https://github.com/CocoaPods/CocoaPods/issues/3276) and monorepo, thus it's hard to create a `.podspec` for this repo.

</Details>

</Step>

<Step
  title="Init LogtoClient"
  subtitle="1 step"
>

You can initialize `LogtoClient` in a proper place of your app that can be accessed globally:

<Code className="language-swift">
    {`import Logto
import LogtoClient

let config = try? LogtoConfig(
  endpoint: "${props.endpoint}",
  appId: "${props.app.id}"
)
let logtoClient = LogtoClient(useConfig: config)`}
</Code>

<br/>

<CustomDomainEndpointNotice />

By default, we store credentials like ID Token and Refresh Token in Keychain. Thus the user doesn't need to sign in again when he returns.

To turn off this behavior, set `usingPersistStorage` to `false`:

```swift
let config = try? LogtoConfig(
  // ...
  usingPersistStorage: false
)
```

</Step>

<Step title="Configure redirect URI">

<RedirectUrisNative />

<InlineNotification>
  The Redirect URI in iOS SDK is only for internal use. There's <em>NO NEED</em> to add a [Custom URL Scheme](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) until a connector asks.
</InlineNotification>

</Step>

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

You can use `client.signInWithBrowser(redirectUri:)` to sign in the user and `client.signOut()` to sign out the user.

For example, in a SwiftUI app:

<Code title="ContentView.swift" className="language-swift">
    {`struct ContentView: View {
  @State var isAuthenticated: Bool

  init() {
    isAuthenticated = client.isAuthenticated
  }

  var body: some View {
    VStack {
      if isAuthenticated {
        Button("Sign Out") {
          Task { [self] in
            await client.signOut()
            isAuthenticated = false
          }
        }
      } else {
        Button("Sign In") {
          Task { [self] in
            do {
              try await client.signInWithBrowser(redirectUri: "${
                props.redirectUris[0] ?? defaultRedirectUri
              }")
              isAuthenticated = true
            } catch let error as LogtoClientErrors.SignIn {
              // error occured during sign in
            } catch {
              // other errors
            }
          }
        }
      }
    }
  }
}`}
</Code>

</Step>

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

<Checkpoint />

</Step>

<Step title="Display user information">

To display the user's information, you can use the `client.getIdTokenClaims()` method. For example, in a SwiftUI app:

<Code title="ContentView.swift" className="language-swift">
    {`struct ContentView: View {
  @State var isAuthenticated: Bool
  @State var name: String?

  init() {
    isAuthenticated = client.isAuthenticated
    name = try? client.getIdTokenClaims().name
  }

  var body: some View {
    VStack {
      if isAuthenticated {
        Text("Welcome, \(name)")
      } else {
        Text("Please sign in")
      }
    }
  }
}`}
</Code>

</Step>

</Steps>
