import { useState } from 'react'
import { nostrAuthService } from '@/lib/nostrAuth'
import { RecoveryStep, ImportStep, ChooseStep } from './CreateAccountModalSteps'

interface CreateAccountModalProps {
  onSuccess: (npub: string) => void
  onClose: () => void
  initialStep?: Step
}

type Step = 'choose' | 'import' | 'recovery'

async function createAccountWithKey(key?: string): Promise<{ recoveryPhrase: string[]; npub: string; publicKey: string }> {
  return nostrAuthService.createAccount(key)
}

async function handleAccountCreation(
  key: string | undefined,
  setLoading: (loading: boolean) => void,
  setError: (error: string | null) => void,
  setRecoveryPhrase: (phrase: string[]) => void,
  setNpub: (npub: string) => void,
  setStep: (step: Step) => void,
  errorMessage: string
): Promise<void> {
  if (key !== undefined && !key.trim()) {
    setError('Please enter a private key')
    return
  }

  setLoading(true)
  setError(null)
  try {
    const result = await createAccountWithKey(key?.trim())
    setRecoveryPhrase(result.recoveryPhrase)
    setNpub(result.npub)
    setStep('recovery')
  } catch (e) {
    setError(e instanceof Error ? e.message : errorMessage)
  } finally {
    setLoading(false)
  }
}

function useAccountCreation(initialStep: Step = 'choose'): {
  step: Step
  setStep: (step: Step) => void
  importKey: string
  setImportKey: (key: string) => void
  loading: boolean
  error: string | null
  setError: (error: string | null) => void
  recoveryPhrase: string[]
  npub: string
  handleGenerate: () => Promise<void>
  handleImport: () => Promise<void>
} {
  const [step, setStep] = useState<Step>(initialStep)
  const [importKey, setImportKey] = useState('')
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [recoveryPhrase, setRecoveryPhrase] = useState<string[]>([])
  const [npub, setNpub] = useState('')

  const handleGenerate = async (): Promise<void> => {
    await handleAccountCreation(undefined, setLoading, setError, setRecoveryPhrase, setNpub, setStep, 'Failed to create account')
  }

  const handleImport = async (): Promise<void> => {
    await handleAccountCreation(importKey, setLoading, setError, setRecoveryPhrase, setNpub, setStep, 'Failed to import key')
  }

  return {
    step,
    setStep,
    importKey,
    setImportKey,
    loading,
    error,
    setError,
    recoveryPhrase,
    npub,
    handleGenerate,
    handleImport,
  }
}

function handleImportBack(setStep: (step: Step) => void, setError: (error: string | null) => void, setImportKey: (key: string) => void): void {
  setStep('choose')
  setError(null)
  setImportKey('')
}

function renderStep(
  step: Step,
  recoveryPhrase: string[],
  npub: string,
  importKey: string,
  setImportKey: (key: string) => void,
  loading: boolean,
  error: string | null,
  handleContinue: () => void,
  handleImport: () => void,
  setStep: (step: Step) => void,
  setError: (error: string | null) => void,
  handleGenerate: () => void,
  onClose: () => void
): React.ReactElement {
  if (step === 'recovery') {
    return <RecoveryStep recoveryPhrase={recoveryPhrase} npub={npub} onContinue={handleContinue} />
  }

  if (step === 'import') {
    return (
      <ImportStep
        importKey={importKey}
        setImportKey={setImportKey}
        loading={loading}
        error={error}
        onImport={handleImport}
        onBack={() => handleImportBack(setStep, setError, setImportKey)}
      />
    )
  }

  return (
    <ChooseStep
      loading={loading}
      error={error}
      onGenerate={handleGenerate}
      onImport={() => setStep('import')}
      onClose={onClose}
    />
  )
}

export function CreateAccountModal({ onSuccess, onClose, initialStep = 'choose' }: CreateAccountModalProps): React.ReactElement {
  const {
    step,
    setStep,
    importKey,
    setImportKey,
    loading,
    error,
    setError,
    recoveryPhrase,
    npub,
    handleGenerate,
    handleImport,
  } = useAccountCreation(initialStep)

  const handleContinue = (): void => {
    onSuccess(npub)
    onClose()
  }

  return renderStep(
    step,
    recoveryPhrase,
    npub,
    importKey,
    setImportKey,
    loading,
    error,
    handleContinue,
    () => { void handleImport() },
    setStep,
    setError,
    () => { void handleGenerate() },
    onClose
  )
}
