import { execa } from 'execa'
import React, { useCallback, useState } from 'react'
import {
  type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
  logEvent,
} from 'src/services/analytics/index.js'
import { WorkflowMultiselectDialog } from '../../components/WorkflowMultiselectDialog.js'
import { GITHUB_ACTION_SETUP_DOCS_URL } from '../../constants/github-app.js'
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js'
import { type KeyboardEvent, Box } from '@anthropic/ink'
import type { LocalJSXCommandOnDone } from '../../types/command.js'
import { getAnthropicApiKey, isAnthropicAuthEnabled } from '../../utils/auth.js'
import { openBrowser } from '../../utils/browser.js'
import { execFileNoThrow } from '../../utils/execFileNoThrow.js'
import { getGithubRepo } from '../../utils/git.js'
import { plural } from '../../utils/stringUtils.js'
import { ApiKeyStep } from './ApiKeyStep.js'
import { CheckExistingSecretStep } from './CheckExistingSecretStep.js'
import { CheckGitHubStep } from './CheckGitHubStep.js'
import { ChooseRepoStep } from './ChooseRepoStep.js'
import { CreatingStep } from './CreatingStep.js'
import { ErrorStep } from './ErrorStep.js'
import { ExistingWorkflowStep } from './ExistingWorkflowStep.js'
import { InstallAppStep } from './InstallAppStep.js'
import { OAuthFlowStep } from './OAuthFlowStep.js'
import { SuccessStep } from './SuccessStep.js'
import { setupGitHubActions } from './setupGitHubActions.js'
import type { State, Warning, Workflow } from './types.js'
import { WarningsStep } from './WarningsStep.js'

const INITIAL_STATE: State = {
  step: 'check-gh',
  selectedRepoName: '',
  currentRepo: '',
  useCurrentRepo: false, // Default to false, will be set to true if repo detected
  apiKeyOrOAuthToken: '',
  useExistingKey: true,
  currentWorkflowInstallStep: 0,
  warnings: [],
  secretExists: false,
  secretName: 'ANTHROPIC_API_KEY',
  useExistingSecret: true,
  workflowExists: false,
  selectedWorkflows: ['claude', 'claude-review'] as Workflow[],
  selectedApiKeyOption: 'new' as 'existing' | 'new' | 'oauth',
  authType: 'api_key',
}

function InstallGitHubApp(props: {
  onDone: (message: string) => void
}): React.ReactNode {
  const [existingApiKey] = useState(() => getAnthropicApiKey())
  const [state, setState] = useState({
    ...INITIAL_STATE,
    useExistingKey: !!existingApiKey,
    selectedApiKeyOption: (existingApiKey
      ? 'existing'
      : isAnthropicAuthEnabled()
        ? 'oauth'
        : 'new') as 'existing' | 'new' | 'oauth',
  })
  useExitOnCtrlCDWithKeybindings()

  React.useEffect(() => {
    logEvent('tengu_install_github_app_started', {})
  }, [])

  const checkGitHubCLI = useCallback(async () => {
    const warnings: Warning[] = []

    // Check if gh is installed
    const ghVersionResult = await execa('gh --version', {
      shell: true,
      reject: false,
    })
    if (ghVersionResult.exitCode !== 0) {
      warnings.push({
        title: 'GitHub CLI not found',
        message:
          'GitHub CLI (gh) does not appear to be installed or accessible.',
        instructions: [
          'Install GitHub CLI from https://cli.github.com/',
          'macOS: brew install gh',
          'Windows: winget install --id GitHub.cli',
          'Linux: See installation instructions at https://github.com/cli/cli#installation',
        ],
      })
    }

    // Check auth status
    const authResult = await execa('gh auth status -a', {
      shell: true,
      reject: false,
    })
    if (authResult.exitCode !== 0) {
      warnings.push({
        title: 'GitHub CLI not authenticated',
        message: 'GitHub CLI does not appear to be authenticated.',
        instructions: [
          'Run: gh auth login',
          'Follow the prompts to authenticate with GitHub',
          'Or set up authentication using environment variables or other methods',
        ],
      })
    } else {
      // Check if required scopes are present in the Token scopes line
      const tokenScopesMatch = authResult.stdout.match(/Token scopes:.*$/m)
      if (tokenScopesMatch) {
        const scopes = tokenScopesMatch[0]
        const missingScopes: string[] = []

        if (!scopes.includes('repo')) {
          missingScopes.push('repo')
        }
        if (!scopes.includes('workflow')) {
          missingScopes.push('workflow')
        }

        if (missingScopes.length > 0) {
          // Missing required scopes - exit immediately
          setState(prev => ({
            ...prev,
            step: 'error',
            error: `GitHub CLI is missing required permissions: ${missingScopes.join(', ')}.`,
            errorReason: 'Missing required scopes',
            errorInstructions: [
              `Your GitHub CLI authentication is missing the "${missingScopes.join('" and "')}" ${plural(missingScopes.length, 'scope')} needed to manage GitHub Actions and secrets.`,
              '',
              'To fix this, run:',
              '  gh auth refresh -h github.com -s repo,workflow',
              '',
              'This will add the necessary permissions to manage workflows and secrets.',
            ],
          }))
          return
        }
      }
    }

    // Check if in a git repo and get remote URL
    const currentRepo = (await getGithubRepo()) ?? ''

    logEvent('tengu_install_github_app_step_completed', {
      step: 'check-gh' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
    })

    setState(prev => ({
      ...prev,
      warnings,
      currentRepo,
      selectedRepoName: currentRepo,
      useCurrentRepo: !!currentRepo, // Set to false if no repo detected
      step: warnings.length > 0 ? 'warnings' : 'choose-repo',
    }))
  }, [])

  React.useEffect(() => {
    if (state.step === 'check-gh') {
      void checkGitHubCLI()
    }
  }, [state.step, checkGitHubCLI])

  const runSetupGitHubActions = useCallback(
    async (apiKeyOrOAuthToken: string | null, secretName: string) => {
      setState(prev => ({
        ...prev,
        step: 'creating',
        currentWorkflowInstallStep: 0,
      }))

      try {
        await setupGitHubActions(
          state.selectedRepoName,
          apiKeyOrOAuthToken,
          secretName,
          () => {
            setState(prev => ({
              ...prev,
              currentWorkflowInstallStep: prev.currentWorkflowInstallStep + 1,
            }))
          },
          state.workflowAction === 'skip',
          state.selectedWorkflows,
          state.authType,
          {
            useCurrentRepo: state.useCurrentRepo,
            workflowExists: state.workflowExists,
            secretExists: state.secretExists,
          },
        )
        logEvent('tengu_install_github_app_step_completed', {
          step: 'creating' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
        })
        setState(prev => ({ ...prev, step: 'success' }))
      } catch (error) {
        const errorMessage =
          error instanceof Error
            ? error.message
            : 'Failed to set up GitHub Actions'

        if (errorMessage.includes('workflow file already exists')) {
          logEvent('tengu_install_github_app_error', {
            reason:
              'workflow_file_exists' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
          })
          setState(prev => ({
            ...prev,
            step: 'error',
            error: 'A Claude workflow file already exists in this repository.',
            errorReason: 'Workflow file conflict',
            errorInstructions: [
              'The file .github/workflows/claude.yml already exists',
              'You can either:',
              '  1. Delete the existing file and run this command again',
              '  2. Update the existing file manually using the template from:',
              `     ${GITHUB_ACTION_SETUP_DOCS_URL}`,
            ],
          }))
        } else {
          logEvent('tengu_install_github_app_error', {
            reason:
              'setup_github_actions_failed' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
          })

          setState(prev => ({
            ...prev,
            step: 'error',
            error: errorMessage,
            errorReason: 'GitHub Actions setup failed',
            errorInstructions: [],
          }))
        }
      }
    },
    [
      state.selectedRepoName,
      state.workflowAction,
      state.selectedWorkflows,
      state.useCurrentRepo,
      state.workflowExists,
      state.secretExists,
      state.authType,
    ],
  )

  async function openGitHubAppInstallation() {
    const installUrl = 'https://github.com/apps/claude'
    await openBrowser(installUrl)
  }

  async function checkRepositoryPermissions(
    repoName: string,
  ): Promise<{ hasAccess: boolean; error?: string }> {
    try {
      const result = await execFileNoThrow('gh', [
        'api',
        `repos/${repoName}`,
        '--jq',
        '.permissions.admin',
      ])

      if (result.code === 0) {
        const hasAdmin = result.stdout.trim() === 'true'
        return { hasAccess: hasAdmin }
      }

      if (
        result.stderr.includes('404') ||
        result.stderr.includes('Not Found')
      ) {
        return {
          hasAccess: false,
          error: 'repository_not_found',
        }
      }

      return { hasAccess: false }
    } catch {
      return { hasAccess: false }
    }
  }

  async function checkExistingWorkflowFile(repoName: string): Promise<boolean> {
    const checkFileResult = await execFileNoThrow('gh', [
      'api',
      `repos/${repoName}/contents/.github/workflows/claude.yml`,
      '--jq',
      '.sha',
    ])

    return checkFileResult.code === 0
  }

  async function checkExistingSecret() {
    const checkSecretsResult = await execFileNoThrow('gh', [
      'secret',
      'list',
      '--app',
      'actions',
      '--repo',
      state.selectedRepoName,
    ])

    if (checkSecretsResult.code === 0) {
      const lines = checkSecretsResult.stdout.split('\n')
      const hasAnthropicKey = lines.some((line: string) => {
        return /^ANTHROPIC_API_KEY\s+/.test(line)
      })

      if (hasAnthropicKey) {
        setState(prev => ({
          ...prev,
          secretExists: true,
          step: 'check-existing-secret',
        }))
      } else {
        // No existing secret found
        if (existingApiKey) {
          // User has local key, skip to creating with it
          setState(prev => ({
            ...prev,
            apiKeyOrOAuthToken: existingApiKey,
            useExistingKey: true,
          }))
          await runSetupGitHubActions(existingApiKey, state.secretName)
        } else {
          // No local key, go to API key step
          setState(prev => ({ ...prev, step: 'api-key' }))
        }
      }
    } else {
      // Error checking secrets
      if (existingApiKey) {
        // User has local key, skip to creating with it
        setState(prev => ({
          ...prev,
          apiKeyOrOAuthToken: existingApiKey,
          useExistingKey: true,
        }))
        await runSetupGitHubActions(existingApiKey, state.secretName)
      } else {
        // No local key, go to API key step
        setState(prev => ({ ...prev, step: 'api-key' }))
      }
    }
  }

  const handleSubmit = async () => {
    if (state.step === 'warnings') {
      logEvent('tengu_install_github_app_step_completed', {
        step: 'warnings' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
      })
      setState(prev => ({ ...prev, step: 'install-app' }))
      setTimeout(openGitHubAppInstallation, 0)
    } else if (state.step === 'choose-repo') {
      let repoName = state.useCurrentRepo
        ? state.currentRepo
        : state.selectedRepoName

      if (!repoName.trim()) {
        return
      }

      const repoWarnings: Warning[] = []

      if (repoName.includes('github.com')) {
        const match = repoName.match(/github\.com[:/]([^/]+\/[^/]+)(\.git)?$/)
        if (!match) {
          repoWarnings.push({
            title: 'Invalid GitHub URL format',
            message: 'The repository URL format appears to be invalid.',
            instructions: [
              'Use format: owner/repo or https://github.com/owner/repo',
              'Example: anthropics/claude-cli',
            ],
          })
        } else {
          repoName = match[1]?.replace(/\.git$/, '') || ''
        }
      }

      if (!repoName.includes('/')) {
        repoWarnings.push({
          title: 'Repository format warning',
          message: 'Repository should be in format "owner/repo"',
          instructions: [
            'Use format: owner/repo',
            'Example: anthropics/claude-cli',
          ],
        })
      }

      const permissionCheck = await checkRepositoryPermissions(repoName)

      if (permissionCheck.error === 'repository_not_found') {
        repoWarnings.push({
          title: 'Repository not found',
          message: `Repository ${repoName} was not found or you don't have access.`,
          instructions: [
            `Check that the repository name is correct: ${repoName}`,
            'Ensure you have access to this repository',
            'For private repositories, make sure your GitHub token has the "repo" scope',
            'You can add the repo scope with: gh auth refresh -h github.com -s repo,workflow',
          ],
        })
      } else if (!permissionCheck.hasAccess) {
        repoWarnings.push({
          title: 'Admin permissions required',
          message: `You might need admin permissions on ${repoName} to set up GitHub Actions.`,
          instructions: [
            'Repository admins can install GitHub Apps and set secrets',
            'Ask a repository admin to run this command if setup fails',
            'Alternatively, you can use the manual setup instructions',
          ],
        })
      }

      const workflowExists = await checkExistingWorkflowFile(repoName)

      if (repoWarnings.length > 0) {
        const allWarnings = [...state.warnings, ...repoWarnings]
        setState(prev => ({
          ...prev,
          selectedRepoName: repoName,
          workflowExists,
          warnings: allWarnings,
          step: 'warnings',
        }))
      } else {
        logEvent('tengu_install_github_app_step_completed', {
          step: 'choose-repo' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
        })
        setState(prev => ({
          ...prev,
          selectedRepoName: repoName,
          workflowExists,
          step: 'install-app',
        }))
        setTimeout(openGitHubAppInstallation, 0)
      }
    } else if (state.step === 'install-app') {
      logEvent('tengu_install_github_app_step_completed', {
        step: 'install-app' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
      })
      if (state.workflowExists) {
        setState(prev => ({ ...prev, step: 'check-existing-workflow' }))
      } else {
        setState(prev => ({ ...prev, step: 'select-workflows' }))
      }
    } else if (state.step === 'check-existing-workflow') {
      return
    } else if (state.step === 'select-workflows') {
      // Handled by the WorkflowMultiselectDialog component
      return
    } else if (state.step === 'check-existing-secret') {
      logEvent('tengu_install_github_app_step_completed', {
        step: 'check-existing-secret' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
      })
      if (state.useExistingSecret) {
        await runSetupGitHubActions(null, state.secretName)
      } else {
        // User wants to use a new secret name with their API key
        await runSetupGitHubActions(state.apiKeyOrOAuthToken, state.secretName)
      }
    } else if (state.step === 'api-key') {
      // In the new flow, api-key step only appears when user has no existing key
      // They either entered a new key or will create OAuth token
      if (state.selectedApiKeyOption === 'oauth') {
        // OAuth flow already handled by handleCreateOAuthToken
        return
      }

      // If user selected 'existing' option, use the existing API key
      const apiKeyToUse =
        state.selectedApiKeyOption === 'existing'
          ? existingApiKey
          : state.apiKeyOrOAuthToken

      if (!apiKeyToUse) {
        logEvent('tengu_install_github_app_error', {
          reason:
            'api_key_missing' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
        })
        setState(prev => ({
          ...prev,
          step: 'error',
          error: 'API key is required',
        }))
        return
      }

      // Store the API key being used (either existing or newly entered)
      setState(prev => ({
        ...prev,
        apiKeyOrOAuthToken: apiKeyToUse,
        useExistingKey: state.selectedApiKeyOption === 'existing',
      }))

      // Check if ANTHROPIC_API_KEY secret already exists
      const checkSecretsResult = await execFileNoThrow('gh', [
        'secret',
        'list',
        '--app',
        'actions',
        '--repo',
        state.selectedRepoName,
      ])

      if (checkSecretsResult.code === 0) {
        const lines = checkSecretsResult.stdout.split('\n')
        const hasAnthropicKey = lines.some((line: string) => {
          return /^ANTHROPIC_API_KEY\s+/.test(line)
        })

        if (hasAnthropicKey) {
          logEvent('tengu_install_github_app_step_completed', {
            step: 'api-key' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
          })
          setState(prev => ({
            ...prev,
            secretExists: true,
            step: 'check-existing-secret',
          }))
        } else {
          logEvent('tengu_install_github_app_step_completed', {
            step: 'api-key' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
          })
          // No existing secret, proceed to creating
          await runSetupGitHubActions(apiKeyToUse, state.secretName)
        }
      } else {
        logEvent('tengu_install_github_app_step_completed', {
          step: 'api-key' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
        })
        // Error checking secrets, proceed anyway
        await runSetupGitHubActions(apiKeyToUse, state.secretName)
      }
    }
  }

  const handleRepoUrlChange = (value: string) => {
    setState(prev => ({ ...prev, selectedRepoName: value }))
  }

  const handleApiKeyChange = (value: string) => {
    setState(prev => ({ ...prev, apiKeyOrOAuthToken: value }))
  }

  const handleApiKeyOptionChange = (option: 'existing' | 'new' | 'oauth') => {
    setState(prev => ({ ...prev, selectedApiKeyOption: option }))
  }

  const handleCreateOAuthToken = useCallback(() => {
    logEvent('tengu_install_github_app_step_completed', {
      step: 'api-key' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
    })
    setState(prev => ({ ...prev, step: 'oauth-flow' }))
  }, [])

  const handleOAuthSuccess = useCallback(
    (token: string) => {
      logEvent('tengu_install_github_app_step_completed', {
        step: 'oauth-flow' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
      })
      setState(prev => ({
        ...prev,
        apiKeyOrOAuthToken: token,
        useExistingKey: false,
        secretName: 'CLAUDE_CODE_OAUTH_TOKEN',
        authType: 'oauth_token',
      }))
      void runSetupGitHubActions(token, 'CLAUDE_CODE_OAUTH_TOKEN')
    },
    [runSetupGitHubActions],
  )

  const handleOAuthCancel = useCallback(() => {
    setState(prev => ({ ...prev, step: 'api-key' }))
  }, [])

  const handleSecretNameChange = (value: string) => {
    if (value && !/^[a-zA-Z0-9_]+$/.test(value)) return
    setState(prev => ({ ...prev, secretName: value }))
  }

  const handleToggleUseCurrentRepo = (useCurrentRepo: boolean) => {
    setState(prev => ({
      ...prev,
      useCurrentRepo,
      selectedRepoName: useCurrentRepo ? prev.currentRepo : '',
    }))
  }

  const handleToggleUseExistingKey = (useExistingKey: boolean) => {
    setState(prev => ({ ...prev, useExistingKey }))
  }

  const handleToggleUseExistingSecret = (useExistingSecret: boolean) => {
    setState(prev => ({
      ...prev,
      useExistingSecret,
      secretName: useExistingSecret ? 'ANTHROPIC_API_KEY' : '',
    }))
  }

  const handleWorkflowAction = async (action: 'update' | 'skip' | 'exit') => {
    if (action === 'exit') {
      props.onDone('Installation cancelled by user')
      return
    }

    logEvent('tengu_install_github_app_step_completed', {
      step: 'check-existing-workflow' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
    })

    setState(prev => ({ ...prev, workflowAction: action }))

    if (action === 'skip' || action === 'update') {
      // Check if user has existing local API key
      if (existingApiKey) {
        await checkExistingSecret()
      } else {
        // No local key, go straight to API key step
        setState(prev => ({ ...prev, step: 'api-key' }))
      }
    }
  }

  function handleDismissKeyDown(e: KeyboardEvent): void {
    e.preventDefault()
    if (state.step === 'success') {
      logEvent('tengu_install_github_app_completed', {})
    }
    props.onDone(
      state.step === 'success'
        ? 'GitHub Actions setup complete!'
        : state.error
          ? `Couldn't install GitHub App: ${state.error}\nFor manual setup instructions, see: ${GITHUB_ACTION_SETUP_DOCS_URL}`
          : `GitHub App installation failed\nFor manual setup instructions, see: ${GITHUB_ACTION_SETUP_DOCS_URL}`,
    )
  }

  switch (state.step) {
    case 'check-gh':
      return <CheckGitHubStep />
    case 'warnings':
      return (
        <WarningsStep warnings={state.warnings} onContinue={handleSubmit} />
      )
    case 'choose-repo':
      return (
        <ChooseRepoStep
          currentRepo={state.currentRepo}
          useCurrentRepo={state.useCurrentRepo}
          repoUrl={state.selectedRepoName}
          onRepoUrlChange={handleRepoUrlChange}
          onToggleUseCurrentRepo={handleToggleUseCurrentRepo}
          onSubmit={handleSubmit}
        />
      )
    case 'install-app':
      return (
        <InstallAppStep
          repoUrl={state.selectedRepoName}
          onSubmit={handleSubmit}
        />
      )
    case 'check-existing-workflow':
      return (
        <ExistingWorkflowStep
          repoName={state.selectedRepoName}
          onSelectAction={handleWorkflowAction}
        />
      )
    case 'check-existing-secret':
      return (
        <CheckExistingSecretStep
          useExistingSecret={state.useExistingSecret}
          secretName={state.secretName}
          onToggleUseExistingSecret={handleToggleUseExistingSecret}
          onSecretNameChange={handleSecretNameChange}
          onSubmit={handleSubmit}
        />
      )
    case 'api-key':
      return (
        <ApiKeyStep
          existingApiKey={existingApiKey}
          useExistingKey={state.useExistingKey}
          apiKeyOrOAuthToken={state.apiKeyOrOAuthToken}
          onApiKeyChange={handleApiKeyChange}
          onToggleUseExistingKey={handleToggleUseExistingKey}
          onSubmit={handleSubmit}
          onCreateOAuthToken={
            isAnthropicAuthEnabled() ? handleCreateOAuthToken : undefined
          }
          selectedOption={state.selectedApiKeyOption}
          onSelectOption={handleApiKeyOptionChange}
        />
      )
    case 'creating':
      return (
        <CreatingStep
          currentWorkflowInstallStep={state.currentWorkflowInstallStep}
          secretExists={state.secretExists}
          useExistingSecret={state.useExistingSecret}
          secretName={state.secretName}
          skipWorkflow={state.workflowAction === 'skip'}
          selectedWorkflows={state.selectedWorkflows}
        />
      )
    case 'success':
      return (
        <Box tabIndex={0} autoFocus onKeyDown={handleDismissKeyDown}>
          <SuccessStep
            secretExists={state.secretExists}
            useExistingSecret={state.useExistingSecret}
            secretName={state.secretName}
            skipWorkflow={state.workflowAction === 'skip'}
          />
        </Box>
      )
    case 'error':
      return (
        <Box tabIndex={0} autoFocus onKeyDown={handleDismissKeyDown}>
          <ErrorStep
            error={state.error}
            errorReason={state.errorReason}
            errorInstructions={state.errorInstructions}
          />
        </Box>
      )
    case 'select-workflows':
      return (
        <WorkflowMultiselectDialog
          defaultSelections={state.selectedWorkflows}
          onSubmit={selectedWorkflows => {
            logEvent('tengu_install_github_app_step_completed', {
              step: 'select-workflows' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
            })
            setState(prev => ({
              ...prev,
              selectedWorkflows,
            }))
            // Check if user has existing local API key
            if (existingApiKey) {
              void checkExistingSecret()
            } else {
              // No local key, go straight to API key step
              setState(prev => ({ ...prev, step: 'api-key' }))
            }
          }}
        />
      )
    case 'oauth-flow':
      return (
        <OAuthFlowStep
          onSuccess={handleOAuthSuccess}
          onCancel={handleOAuthCancel}
        />
      )
  }
}

export async function call(
  onDone: LocalJSXCommandOnDone,
): Promise<React.ReactNode> {
  return <InstallGitHubApp onDone={onDone} />
}
