import { useEffect } from 'react'
import { useForm, Controller } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { toast } from 'sonner'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { RefreshCwIcon } from 'lucide-react'

import { SettingRow } from '@/components/setting-row'
import { LoadingButton } from '@/components/loading-button'
import { FieldGroup } from '@cfdm/ui/components/field'
import { Input } from '@cfdm/ui/components/input'
import { Button } from '@cfdm/ui/components/button'
import { Switch } from '@cfdm/ui/components/switch'
import { api, ApiError } from '@/lib/api-client'
import { snapshotQueryOptions } from '@/queries/snapshot'
import type { Settings } from '@/types/entities'

const formSchema = z.object({
  cfdmApiUrl: z.string().optional().default(''),
  integrationToken: z.string().optional().default(''),
  integrationEnabled: z.boolean().default(false),
})

type FormValues = z.infer<typeof formSchema>

function generateToken(): string {
  const bytes = new Uint8Array(24)
  crypto.getRandomValues(bytes)
  return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')
}

interface CfdmIntegrationFormProps {
  settings?: Settings
  /** URL CFDM из App Switcher (portal) — только подсказка для заполнения поля */
  fallbackCfdmUrl?: string
  onSave: (values: {
    cfdmApiUrl?: string
    integrationToken?: string
    integrationEnabled: boolean
  }) => void
  isSaving?: boolean
}

/** CFDM integration form — Frame/SettingRow. Preview https://reui.io/preview/base/settings-2 · https://reui.io/preview/base/settings-16 */
export function CfdmIntegrationForm({
  settings,
  fallbackCfdmUrl,
  onSave,
  isSaving,
}: CfdmIntegrationFormProps) {
  const queryClient = useQueryClient()
  const savedUrl = settings?.cfdmApiUrl?.trim() ?? ''
  const switcherUrl = fallbackCfdmUrl?.trim() || ''

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    values: {
      cfdmApiUrl: savedUrl,
      integrationToken: '',
      integrationEnabled: Boolean(settings?.integrationEnabled),
    },
  })

  // Если URL ещё не сохранён в settings — подставить prod URL из App Switcher и включить «Сохранить».
  useEffect(() => {
    if (savedUrl || !switcherUrl) return
    if (form.getValues('cfdmApiUrl')?.trim()) return
    form.setValue('cfdmApiUrl', switcherUrl, { shouldDirty: true, shouldTouch: true })
  }, [savedUrl, switcherUrl, form])

  const syncMut = useMutation({
    mutationFn: () => api.syncCfdm(),
    onSuccess: async (result) => {
      await queryClient.invalidateQueries({ queryKey: snapshotQueryOptions().queryKey })
      toast.success(
        result.count != null
          ? `Синхронизация завершена: ${result.count} bindings`
          : 'Синхронизация завершена',
      )
    },
    onError: (e: unknown) => {
      toast.error(e instanceof ApiError ? e.message : 'Не удалось синхронизировать с CFDM')
    },
  })

  function handleSubmit(values: FormValues) {
    const token = values.integrationToken?.trim()
    const url = values.cfdmApiUrl?.trim() ?? ''
    onSave({
      integrationEnabled: values.integrationEnabled,
      // Всегда пишем явное значение — иначе URL не попадает в БД.
      cfdmApiUrl: url,
      ...(token ? { integrationToken: token } : {}),
    })
  }

  const hasSavedToken = Boolean(settings?.integrationTokenSet)
  const hasSavedUrl = Boolean(savedUrl)
  const canSync = hasSavedToken && hasSavedUrl

  return (
    <form
      className="flex flex-col gap-0"
      onSubmit={(e) => void form.handleSubmit(handleSubmit)(e)}
    >
      <FieldGroup className="gap-0">
        <SettingRow
          title="Принимать синхронизацию"
          description="Вкл.: push от CFDM + авто-pull доменов каждые 15 мин (нужны URL и токен)"
        >
          <Controller
            control={form.control}
            name="integrationEnabled"
            render={({ field }) => (
              <Switch
                checked={Boolean(field.value)}
                onCheckedChange={field.onChange}
                aria-label="Принимать синхронизацию"
              />
            )}
          />
        </SettingRow>
        <SettingRow
          title="URL API CFDM"
          description={
            hasSavedUrl
              ? `Сохранён: ${savedUrl}`
              : switcherUrl
                ? `Не сохранён в БД. Подставлен URL из App Switcher — нажмите «Сохранить интеграцию»`
                : 'Укажите продовый URL API CFDM и сохраните'
          }
          labelFor="cfdm-api-url"
          stacked
        >
          <Input
            id="cfdm-api-url"
            className="w-full"
            placeholder="https://cfdm.example.org"
            {...form.register('cfdmApiUrl')}
          />
        </SettingRow>
        <SettingRow
          title="Integration token"
          description={
            hasSavedToken
              ? 'Токен сохранён — введите новый только для замены'
              : 'Сгенерируйте или вставьте токен, затем сохраните'
          }
          labelFor="integration-token"
          stacked
        >
          <div className="flex w-full flex-col gap-2 sm:flex-row">
            <Input
              id="integration-token"
              type="password"
              autoComplete="new-password"
              className="min-w-0 flex-1"
              placeholder={
                hasSavedToken
                  ? 'Токен сохранён — введите новый для замены'
                  : 'Сгенерируйте или вставьте токен'
              }
              {...form.register('integrationToken')}
            />
            <Button
              type="button"
              variant="outline"
              size="sm"
              className="shrink-0"
              onClick={() => {
                const token = generateToken()
                form.setValue('integrationToken', token, { shouldDirty: true })
                void navigator.clipboard.writeText(token)
                toast.success('Токен сгенерирован и скопирован')
              }}
            >
              Сгенерировать
            </Button>
          </div>
        </SettingRow>
        <SettingRow
          title="Синхронизация"
          description={
            settings?.integrationLastSyncAt
              ? `Последний sync: ${new Date(settings.integrationLastSyncAt).toLocaleString('ru-RU')} · авто каждые 15 мин`
              : 'Авто каждые 15 мин при включённой интеграции; кнопка — ручной pull'
          }
          last
        >
          <LoadingButton
            type="button"
            variant="outline"
            size="sm"
            loading={syncMut.isPending}
            disabled={syncMut.isPending || !canSync}
            title={
              canSync
                ? `Синхронизировать с ${savedUrl}`
                : !hasSavedUrl
                  ? 'Сначала сохраните URL API CFDM'
                  : 'Сначала сохраните integration token'
            }
            onClick={() => {
              if (!hasSavedUrl) {
                toast.error('Сначала сохраните URL API CFDM (кнопка «Сохранить интеграцию»)')
                return
              }
              if (!hasSavedToken) {
                toast.error('Сначала сохраните integration token')
                return
              }
              syncMut.mutate()
            }}
          >
            <RefreshCwIcon data-icon="inline-start" aria-hidden="true" />
            Синхронизировать
          </LoadingButton>
        </SettingRow>
      </FieldGroup>
      <div className="flex justify-end border-t px-5 py-3">
        <LoadingButton
          type="submit"
          loading={isSaving}
          disabled={!form.formState.isDirty}
        >
          Сохранить интеграцию
        </LoadingButton>
      </div>
    </form>
  )
}

/** @deprecated Use CfdmIntegrationForm */
export const CfdmIntegrationCard = CfdmIntegrationForm
