import { useState, useCallback, useEffect, type FormEvent } from 'react'
import { useRouter } from 'next/router'
import { useNostrAuth } from '@/hooks/useNostrAuth'
import { useAuthorPresentation } from '@/hooks/useAuthorPresentation'
import { ArticleField } from './ArticleField'
import { CreateAccountModal } from './CreateAccountModal'
import { RecoveryStep } from './CreateAccountModalSteps'
import { UnlockAccountModal } from './UnlockAccountModal'
import { ImageUploadField } from './ImageUploadField'
import { PresentationFormHeader } from './PresentationFormHeader'
import { extractPresentationData } from '@/lib/presentationParsing'
import type { Article } from '@/types/nostr'
import { t } from '@/lib/i18n'
import { userConfirm } from '@/lib/userConfirm'

interface AuthorPresentationDraft {
  authorName: string
  presentation: string
  contentDescription: string
  mainnetAddress: string
  pictureUrl?: string
}

const ADDRESS_PATTERN = /^(1|3|bc1)[a-zA-Z0-9]{25,62}$/

function SuccessNotice({ pubkey }: { pubkey: string | null }): React.ReactElement {
  return (
    <div className="border border-neon-green/50 rounded-lg p-6 bg-neon-green/10">
      <h3 className="text-lg font-semibold text-neon-green mb-2">{t('presentation.success')}</h3>
      <p className="text-cyber-accent mb-4">
        {t('presentation.successMessage')}
      </p>
      {pubkey && (
        <div className="mt-4">
          <a
            href={`/author/${pubkey}`}
            className="inline-block px-4 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan"
          >
            {t('presentation.manageSeries')}
          </a>
        </div>
      )}
    </div>
  )
}

function ValidationError({ message }: { message: string | null }): React.ReactElement | null {
  if (!message) {
    return null
  }
  return (
    <div className="bg-red-500/10 border border-red-500/50 rounded-lg p-3">
      <p className="text-sm text-red-400">{message}</p>
    </div>
  )
}

function PresentationField({
  draft,
  onChange,
}: {
  draft: AuthorPresentationDraft
  onChange: (next: AuthorPresentationDraft) => void
}): React.ReactElement {
  return (
    <ArticleField
      id="presentation"
      label={t('presentation.field.presentation')}
      value={draft.presentation}
      onChange={(value) => onChange({ ...draft, presentation: value as string })}
      required
      type="textarea"
      rows={6}
      placeholder={t('presentation.field.presentation.placeholder')}
      helpText={t('presentation.field.presentation.help')}
    />
  )
}

function ContentDescriptionField({
  draft,
  onChange,
}: {
  draft: AuthorPresentationDraft
  onChange: (next: AuthorPresentationDraft) => void
}): React.ReactElement {
  return (
    <ArticleField
      id="contentDescription"
      label={t('presentation.field.contentDescription')}
      value={draft.contentDescription}
      onChange={(value) => onChange({ ...draft, contentDescription: value as string })}
      required
      type="textarea"
      rows={6}
      placeholder={t('presentation.field.contentDescription.placeholder')}
      helpText={t('presentation.field.contentDescription.help')}
    />
  )
}

function MainnetAddressField({
  draft,
  onChange,
}: {
  draft: AuthorPresentationDraft
  onChange: (next: AuthorPresentationDraft) => void
}): React.ReactElement {
  return (
    <ArticleField
      id="mainnetAddress"
      label={t('presentation.field.mainnetAddress')}
      value={draft.mainnetAddress}
      onChange={(value) => onChange({ ...draft, mainnetAddress: value as string })}
      required
      type="text"
      placeholder={t('presentation.field.mainnetAddress.placeholder')}
      helpText={t('presentation.field.mainnetAddress.help')}
    />
  )
}

function AuthorNameField({
  draft,
  onChange,
}: {
  draft: AuthorPresentationDraft
  onChange: (next: AuthorPresentationDraft) => void
}): React.ReactElement {
  return (
    <ArticleField
      id="authorName"
      label={t('presentation.field.authorName')}
      value={draft.authorName}
      onChange={(value) => onChange({ ...draft, authorName: value as string })}
      required
      type="text"
      placeholder={t('presentation.field.authorName.placeholder')}
      helpText={t('presentation.field.authorName.help')}
    />
  )
}

function PictureField({
  draft,
  onChange,
}: {
  draft: AuthorPresentationDraft
  onChange: (next: AuthorPresentationDraft) => void
}): React.ReactElement {
  return (
    <ImageUploadField
      id="picture"
      value={draft.pictureUrl}
      onChange={(url) => onChange({ ...draft, pictureUrl: url })}
    />
  )
}

const PresentationFields = ({
  draft,
  onChange,
}: {
  draft: AuthorPresentationDraft
  onChange: (next: AuthorPresentationDraft) => void
}): React.ReactElement => (
  <div className="space-y-4">
    <AuthorNameField draft={draft} onChange={onChange} />
    <PictureField draft={draft} onChange={onChange} />
    <PresentationField draft={draft} onChange={onChange} />
    <ContentDescriptionField draft={draft} onChange={onChange} />
    <MainnetAddressField draft={draft} onChange={onChange} />
  </div>
)

function DeleteButton({ onDelete, deleting }: { onDelete: () => void; deleting: boolean }): React.ReactElement {
  return (
    <button
      type="button"
      onClick={onDelete}
      disabled={deleting}
      className="px-4 py-2 bg-red-500/20 hover:bg-red-500/30 text-red-400 rounded-lg text-sm font-medium transition-all border border-red-500/50 hover:shadow-glow-red disabled:opacity-50"
    >
      {deleting ? t('presentation.delete.deleting') : t('presentation.delete.button')}
    </button>
  )
}

type PresentationFormProps = {
  draft: AuthorPresentationDraft
  setDraft: (next: AuthorPresentationDraft) => void
  validationError: string | null
  error: string | null
  loading: boolean
  handleSubmit: (e: FormEvent<HTMLFormElement>) => Promise<void>
  deleting: boolean
  handleDelete: () => void
  hasExistingPresentation: boolean
}

function PresentationForm(props: PresentationFormProps): React.ReactElement {
  return (
    <form
      onSubmit={(e: FormEvent<HTMLFormElement>) => {
        void props.handleSubmit(e)
      }}
      className="border border-neon-cyan/20 rounded-lg p-6 bg-cyber-dark space-y-4"
    >
      <PresentationFormHeader />
      <PresentationFields draft={props.draft} onChange={props.setDraft} />
      <ValidationError message={props.validationError ?? props.error} />
      <div className="flex items-center gap-4">
        <div className="flex-1">
          <button
            type="submit"
            disabled={props.loading ?? props.deleting}
            className="w-full px-4 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan disabled:opacity-50 disabled:cursor-not-allowed"
          >
            {getSubmitLabel(props)}
          </button>
        </div>
        {props.hasExistingPresentation && (
          <DeleteButton onDelete={() => { void props.handleDelete() }} deleting={props.deleting} />
        )}
      </div>
    </form>
  )
}

function getSubmitLabel(params: { loading: boolean; deleting: boolean; hasExistingPresentation: boolean }): string {
  if (params.loading || params.deleting) {
    return t('publish.publishing')
  }
  return params.hasExistingPresentation ? t('presentation.update.button') : t('publish.button')
}

function useAuthorPresentationState(pubkey: string | null, existingAuthorName?: string, existingPresentation?: Article | null): {
  draft: AuthorPresentationDraft
  setDraft: (next: AuthorPresentationDraft) => void
  validationError: string | null
  error: string | null
  loading: boolean
  handleSubmit: (e: FormEvent<HTMLFormElement>) => Promise<void>
  deleting: boolean
  handleDelete: () => Promise<void>
  success: boolean
} {
  const { loading, error, success, publishPresentation, deletePresentation } = useAuthorPresentation(pubkey)
  const router = useRouter()
  const [draft, setDraft] = useState<AuthorPresentationDraft>(() => buildInitialDraft(existingPresentation, existingAuthorName))
  const [validationError, setValidationError] = useState<string | null>(null)
  const [deleting, setDeleting] = useState(false)

  // Update authorName when profile changes
  useEffect(() => {
    syncAuthorNameIntoDraft({ existingAuthorName, draftAuthorName: draft.authorName, hasExistingPresentation: Boolean(existingPresentation), setDraft })
  }, [existingAuthorName, existingPresentation, draft.authorName])

  const handleSubmit = useCallback(
    async (e: FormEvent<HTMLFormElement>) => {
      e.preventDefault()
      await submitPresentationDraft({ draft, setValidationError, publishPresentation })
    },
    [draft, publishPresentation]
  )

  const handleDelete = useCallback(async () => {
    await deletePresentationFlow({
      existingPresentationId: existingPresentation?.id,
      deletePresentation,
      router,
      setDeleting,
      setValidationError,
    })
  }, [existingPresentation, deletePresentation, router])

  return { loading, error, success, draft, setDraft, validationError, handleSubmit, deleting, handleDelete }
}

function buildInitialDraft(existingPresentation: Article | null | undefined, existingAuthorName: string | undefined): AuthorPresentationDraft {
  if (existingPresentation) {
    const { presentation, contentDescription } = extractPresentationData(existingPresentation)
    const authorName = existingPresentation.title.replace(/^Présentation de /, '') ?? existingAuthorName ?? ''
    return {
      authorName,
      presentation,
      contentDescription,
      mainnetAddress: existingPresentation.mainnetAddress ?? '',
      ...(existingPresentation.bannerUrl ? { pictureUrl: existingPresentation.bannerUrl } : {}),
    }
  }
  return {
    authorName: existingAuthorName ?? '',
    presentation: '',
    contentDescription: '',
    mainnetAddress: '',
  }
}

function syncAuthorNameIntoDraft(params: {
  existingAuthorName: string | undefined
  draftAuthorName: string
  hasExistingPresentation: boolean
  setDraft: (updater: (prev: AuthorPresentationDraft) => AuthorPresentationDraft) => void
}): void {
  if (!params.existingAuthorName || params.hasExistingPresentation || params.existingAuthorName === params.draftAuthorName) {
    return
  }
  params.setDraft((prev) => ({ ...prev, authorName: params.existingAuthorName as string }))
}

async function submitPresentationDraft(params: {
  draft: AuthorPresentationDraft
  setValidationError: (value: string | null) => void
  publishPresentation: (draft: AuthorPresentationDraft) => Promise<void>
}): Promise<void> {
  const error = validatePresentationDraft(params.draft)
  if (error) {
    params.setValidationError(error)
    return
  }
  params.setValidationError(null)
  await params.publishPresentation(params.draft)
}

function validatePresentationDraft(draft: AuthorPresentationDraft): string | null {
  const address = draft.mainnetAddress.trim()
  if (!ADDRESS_PATTERN.test(address)) {
    return t('presentation.validation.invalidAddress')
  }
  if (!draft.authorName.trim()) {
    return t('presentation.validation.authorNameRequired')
  }
  return null
}

async function deletePresentationFlow(params: {
  existingPresentationId: string | undefined
  deletePresentation: (articleId: string) => Promise<void>
  router: ReturnType<typeof useRouter>
  setDeleting: (value: boolean) => void
  setValidationError: (value: string | null) => void
}): Promise<void> {
  if (!params.existingPresentationId) {
    return
  }
  const confirmed = await userConfirm(t('presentation.delete.confirm'))
  if (!confirmed) {
    return
  }
  params.setDeleting(true)
  params.setValidationError(null)
  try {
    await params.deletePresentation(params.existingPresentationId)
    await params.router.push('/')
  } catch (e) {
    params.setValidationError(e instanceof Error ? e.message : t('presentation.delete.error'))
  } finally {
    params.setDeleting(false)
  }
}

function NoAccountActionButtons({
  onGenerate,
  onImport,
}: {
  onGenerate: () => void
  onImport: () => void
}): React.ReactElement {
  return (
    <div className="flex flex-col gap-3 w-full max-w-xs">
      <button
        onClick={onGenerate}
        className="px-6 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan"
      >
        {t('account.create.generateButton')}
      </button>
      <button
        onClick={onImport}
        className="px-6 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg font-medium transition-colors"
      >
        {t('account.create.importButton')}
      </button>
    </div>
  )
}

function NoAccountView(): React.ReactElement {
  const [showImportModal, setShowImportModal] = useState(false)
  const [showRecoveryStep, setShowRecoveryStep] = useState(false)
  const [showUnlockModal, setShowUnlockModal] = useState(false)
  const [recoveryPhrase, setRecoveryPhrase] = useState<string[]>([])
  const [npub, setNpub] = useState('')
  const [generating, setGenerating] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const handleGenerate = (): Promise<void> => generateNoAccount({ setGenerating, setError, setRecoveryPhrase, setNpub, setShowRecoveryStep })
  const handleRecoveryContinue = (): void => transitionToUnlock({ setShowRecoveryStep, setShowUnlockModal })
  const handleUnlockSuccess = (): void => resetNoAccountAfterUnlock({ setShowUnlockModal, setRecoveryPhrase, setNpub })
  const handleImportSuccess = (): void => {
    setShowImportModal(false)
    setShowUnlockModal(true)
  }

  return (
    <NoAccountCard
      error={error}
      generating={generating}
      onGenerate={() => { void handleGenerate() }}
      onImport={() => setShowImportModal(true)}
      modals={
        <NoAccountModals
          showImportModal={showImportModal}
          onCloseImport={() => setShowImportModal(false)}
          onImportSuccess={handleImportSuccess}
          showRecoveryStep={showRecoveryStep}
          recoveryPhrase={recoveryPhrase}
          npub={npub}
          onRecoveryContinue={handleRecoveryContinue}
          showUnlockModal={showUnlockModal}
          onUnlockSuccess={handleUnlockSuccess}
          onCloseUnlock={() => setShowUnlockModal(false)}
        />
      }
    />
  )
}

async function generateNoAccount(params: {
  setGenerating: (value: boolean) => void
  setError: (value: string | null) => void
  setRecoveryPhrase: (value: string[]) => void
  setNpub: (value: string) => void
  setShowRecoveryStep: (value: boolean) => void
}): Promise<void> {
  params.setGenerating(true)
  params.setError(null)
  try {
    const { nostrAuthService } = await import('@/lib/nostrAuth')
    const result = await nostrAuthService.createAccount()
    params.setRecoveryPhrase(result.recoveryPhrase)
    params.setNpub(result.npub)
    params.setShowRecoveryStep(true)
  } catch (e) {
    params.setError(e instanceof Error ? e.message : t('account.create.error.failed'))
  } finally {
    params.setGenerating(false)
  }
}

function transitionToUnlock(params: { setShowRecoveryStep: (value: boolean) => void; setShowUnlockModal: (value: boolean) => void }): void {
  params.setShowRecoveryStep(false)
  params.setShowUnlockModal(true)
}

function resetNoAccountAfterUnlock(params: {
  setShowUnlockModal: (value: boolean) => void
  setRecoveryPhrase: (value: string[]) => void
  setNpub: (value: string) => void
}): void {
  params.setShowUnlockModal(false)
  params.setRecoveryPhrase([])
  params.setNpub('')
}

function NoAccountCard(params: {
  error: string | null
  generating: boolean
  onGenerate: () => void
  onImport: () => void
  modals: React.ReactElement
}): React.ReactElement {
  return (
    <div className="border border-neon-cyan/20 rounded-lg p-6 bg-cyber-dark/50">
      <div className="flex flex-col items-center gap-4">
        <p className="text-center text-cyber-accent mb-2">Créez un compte ou importez votre clé secrète pour commencer</p>
        {params.error && <p className="text-sm text-red-400">{params.error}</p>}
        <NoAccountActionButtons onGenerate={params.onGenerate} onImport={params.onImport} />
        {params.generating && <p className="text-cyber-accent text-sm">Génération du compte...</p>}
        {params.modals}
      </div>
    </div>
  )
}

function NoAccountModals(params: {
  showImportModal: boolean
  onImportSuccess: () => void
  onCloseImport: () => void
  showRecoveryStep: boolean
  recoveryPhrase: string[]
  npub: string
  onRecoveryContinue: () => void
  showUnlockModal: boolean
  onUnlockSuccess: () => void
  onCloseUnlock: () => void
}): React.ReactElement {
  return (
    <>
      {params.showImportModal && <CreateAccountModal onSuccess={params.onImportSuccess} onClose={params.onCloseImport} initialStep="import" />}
      {params.showRecoveryStep && <RecoveryStep recoveryPhrase={params.recoveryPhrase} npub={params.npub} onContinue={params.onRecoveryContinue} />}
      {params.showUnlockModal && <UnlockAccountModal onSuccess={params.onUnlockSuccess} onClose={params.onCloseUnlock} />}
    </>
  )
}

function AuthorPresentationFormView(props: {
  pubkey: string | null
  profile: { name?: string; pubkey: string } | null
}): React.ReactElement {
  const { checkPresentationExists } = useAuthorPresentation(props.pubkey)
  const presentation = useExistingPresentation({ pubkey: props.pubkey, checkPresentationExists })
  const state = useAuthorPresentationState(props.pubkey, props.profile?.name, presentation.existingPresentation)

  if (!props.pubkey) {
    return <NoAccountView />
  }
  if (presentation.loadingPresentation) {
    return <LoadingNotice />
  }
  if (state.success) {
    return <SuccessNotice pubkey={props.pubkey} />
  }
  return (
    <PresentationForm
      draft={state.draft}
      setDraft={state.setDraft}
      validationError={state.validationError}
      error={state.error}
      loading={state.loading}
      handleSubmit={state.handleSubmit}
      deleting={state.deleting}
      handleDelete={() => { void state.handleDelete() }}
      hasExistingPresentation={presentation.existingPresentation !== null}
    />
  )
}

function LoadingNotice(): React.ReactElement {
  return (
    <div className="text-center py-12">
      <p className="text-cyber-accent/70">{t('common.loading')}</p>
    </div>
  )
}

function useExistingPresentation(params: {
  pubkey: string | null
  checkPresentationExists: () => Promise<Article | null>
}): { existingPresentation: Article | null; loadingPresentation: boolean } {
  const [existingPresentation, setExistingPresentation] = useState<Article | null>(null)
  const [loadingPresentation, setLoadingPresentation] = useState(true)
  const { pubkey, checkPresentationExists } = params

  useEffect(() => {
    void loadExistingPresentation({ pubkey, checkPresentationExists, setExistingPresentation, setLoadingPresentation })
  }, [pubkey, checkPresentationExists])

  return { existingPresentation, loadingPresentation }
}

async function loadExistingPresentation(params: {
  pubkey: string | null
  checkPresentationExists: () => Promise<Article | null>
  setExistingPresentation: (value: Article | null) => void
  setLoadingPresentation: (value: boolean) => void
}): Promise<void> {
  if (!params.pubkey) {
    params.setLoadingPresentation(false)
    return
  }
  try {
    params.setExistingPresentation(await params.checkPresentationExists())
  } catch (e) {
    console.error('Error loading presentation:', e)
  } finally {
    params.setLoadingPresentation(false)
  }
}

function useAutoLoadPubkey(accountExists: boolean | null, pubkey: string | null, connect: () => Promise<void>): void {
  useEffect(() => {
    if (accountExists === true && !pubkey) {
      void connect()
    }
  }, [accountExists, pubkey, connect])
}

export function AuthorPresentationEditor(): React.ReactElement {
  const { pubkey, profile, accountExists, connect } = useNostrAuth()
  useAutoLoadPubkey(accountExists, pubkey ?? null, connect)
  return <AuthorPresentationFormView pubkey={pubkey ?? null} profile={profile} />
}
