import { getGetServerSideProps } from '@/api/ssrApollo'
import { Form, ClientInput, ClientCheckbox, PasswordInput, CheckboxGroup } from '@/components/form'
import { CenterLayout } from '@/components/layout'
import { WalletSecurityBanner } from '@/components/banners'
import { WalletLogs } from '@/components/wallet-logger'
import { useToast } from '@/components/toast'
import { useRouter } from 'next/router'
import { useWallet, Status } from 'wallets'
import Info from '@/components/info'
import Text from '@/components/text'
import { AutowithdrawSettings } from '@/components/autowithdraw-shared'
import dynamic from 'next/dynamic'

const WalletButtonBar = dynamic(() => import('@/components/wallet-buttonbar.js'), { ssr: false })

export const getServerSideProps = getGetServerSideProps({ authRequired: true })

export default function WalletSettings () {
  const toaster = useToast()
  const router = useRouter()
  const { wallet: name } = router.query
  const wallet = useWallet(name)

  const initial = wallet.fields.reduce((acc, field) => {
    // We still need to run over all wallet fields via reduce
    // even though we use wallet.config as the initial value
    // since wallet.config is empty when wallet is not configured.
    // Also, wallet.config includes general fields like
    // 'enabled' and 'priority' which are not defined in wallet.fields.
    return {
      ...acc,
      [field.name]: wallet.config?.[field.name] || ''
    }
  }, wallet.config)

  // check if wallet uses the form-level validation built into Formik or a Yup schema
  const validateProps = typeof wallet.fieldValidation === 'function'
    ? { validate: wallet.fieldValidation }
    : { schema: wallet.fieldValidation }

  return (
    <CenterLayout>
      <h2 className='pb-2'>{wallet.card.title}</h2>
      <h6 className='text-muted text-center pb-3'><Text>{wallet.card.subtitle}</Text></h6>
      {!wallet.walletType && wallet.hasConfig > 0 && <WalletSecurityBanner />}
      <Form
        initial={initial}
        {...validateProps}
        onSubmit={async ({ amount, ...values }) => {
          try {
            const newConfig = !wallet.isConfigured

            // enable wallet if wallet was just configured
            if (newConfig) {
              values.enabled = true
            }

            await wallet.save(values)

            toaster.success('saved settings')
            router.push('/settings/wallets')
          } catch (err) {
            console.error(err)
            toaster.danger(err.message || err.toString?.())
          }
        }}
      >
        <WalletFields wallet={wallet} />
        {wallet.walletType
          ? <AutowithdrawSettings wallet={wallet} />
          : (
            <CheckboxGroup name='enabled'>
              <ClientCheckbox
                disabled={!wallet.isConfigured}
                initialValue={wallet.status === Status.Enabled}
                label='enabled'
                name='enabled'
                groupClassName='mb-0'
              />
            </CheckboxGroup>
            )}
        <WalletButtonBar
          wallet={wallet} onDelete={async () => {
            try {
              await wallet.delete()
              toaster.success('saved settings')
              router.push('/settings/wallets')
            } catch (err) {
              console.error(err)
              const message = 'failed to detach: ' + err.message || err.toString?.()
              toaster.danger(message)
            }
          }}
        />
      </Form>
      <div className='mt-3 w-100'>
        <WalletLogs wallet={wallet} embedded />
      </div>
    </CenterLayout>
  )
}

function WalletFields ({ wallet: { config, fields, isConfigured } }) {
  return fields
    .map(({ name, label = '', type, help, optional, editable, clientOnly, serverOnly, ...props }, i) => {
      const rawProps = {
        ...props,
        name,
        initialValue: config?.[name],
        readOnly: isConfigured && editable === false && !!config?.[name],
        groupClassName: props.hidden ? 'd-none' : undefined,
        label: label
          ? (
            <div className='d-flex align-items-center'>
              {label}
              {/* help can be a string or object to customize the label */}
              {help && (
                <Info label={help.label}>
                  <Text>{help.text || help}</Text>
                </Info>
              )}
              {optional && (
                <small className='text-muted ms-2'>
                  {typeof optional === 'boolean' ? 'optional' : <Text>{optional}</Text>}
                </small>
              )}
            </div>
            )
          : undefined,
        required: !optional,
        autoFocus: i === 0
      }
      if (type === 'text') {
        return <ClientInput key={i} {...rawProps} />
      }
      if (type === 'password') {
        return <PasswordInput key={i} {...rawProps} newPass />
      }
      return null
    })
}