import { PlusIcon, SparklesIcon } from 'lucide-react'
import { useState } from 'react'

import { FieldError, fieldErrorProps } from '@/components/FieldError'
import { SectionCard } from '@/components/SectionCard'
import { Button } from '@/components/ui/button'
import { FieldDescription } from '@/components/ui/field'
import { Spinner } from '@/components/ui/spinner'
import { Textarea } from '@/components/ui/textarea'
import { formatNumber } from '@/lib/format'
import { t } from '@/lib/i18n'

interface Props {
  notes: string
  /** El tope que fija el servidor. El campo no deja pasarlo. */
  maxLength: number
  onChange: (notes: string) => void
  error?: string
  /** Si todos los contenedores tienen servicio y sus obligatorios contestados. */
  complete: boolean
  submitting: boolean
  /** Un error del pedido entero —la lista, el análisis—, que no pertenece a ningún campo. */
  requestError?: string
}

const NOTES_ID = 'notes'
const NOTES_ERROR_ID = 'error-notes'

/**
 * Las notas libres: lo único del pedido que la persona redacta.
 *
 * Todo lo demás sale del catálogo, y eso es lo que hace que dos pedidos iguales
 * den el mismo prompt. Pero el catálogo no puede anticipar lo que sólo se ve en
 * esa foto —«donde puse un 1, va el adoquín oscuro»—, y sin un lugar para
 * decirlo la única salida es no pedirlo.
 *
 * Arranca cerrada, detrás de un botón, porque el caso normal es no escribir
 * nada: un campo de texto siempre a la vista se lee como algo que hay que
 * completar. Lo que la nota **no** va a conseguir se lee arriba, en la tarjeta
 * de guards: ahí están las reglas y ahí se bajan las que se pueden bajar.
 *
 * El botón de generar vive en su pie, aunque el botón no sea de las notas: es
 * la última tarjeta del recorrido, y la acción del formulario entero tiene que
 * estar donde termina de contestarse, no colgando de lo que antes era la
 * tarjeta del prompt. Está siempre, se escriban notas o no, y dice al lado por
 * qué no se puede apretar: un botón apagado sin explicación se lee como una
 * pantalla rota.
 */
export function NotesSection({
  notes,
  maxLength,
  onChange,
  error,
  complete,
  submitting,
  requestError,
}: Props) {
  // Abierta desde que hay algo escrito: un pedido que se ajusta vuelve con sus
  // notas puestas, y esconderlas detrás del botón sería esconder algo que ya va
  // a viajar en el prompt.
  const [open, setOpen] = useState(notes !== '')

  const close = () => {
    // Sacar la caja es sacar las notas. Guardarlas cerradas dejaría un texto
    // invisible entrando al prompt.
    onChange('')
    setOpen(false)
  }

  return (
    <SectionCard
      title={{ text: t('ai.notes.title') }}
      description={t('ai.notes.description')}
      id="notes"
      footer={
        <div className="flex flex-col gap-2">
          <FieldError id="error-request" message={requestError} />
          <div className="flex flex-wrap items-center gap-3">
            <Button type="submit" disabled={submitting || !complete}>
              {submitting ? <Spinner /> : <SparklesIcon aria-hidden />}
              {submitting ? t('ai.generator.submitting') : t('ai.generator.submit')}
            </Button>
            {!complete ? (
              <p className="text-muted-foreground text-xs">{t('ai.generator.incomplete')}</p>
            ) : null}
          </div>
        </div>
      }
    >
      {open ? (
        <div className="flex flex-col gap-3">
          <div className="flex flex-col gap-2">
            <Textarea
              id={NOTES_ID}
              value={notes}
              rows={4}
              maxLength={maxLength}
              placeholder={t('ai.notes.placeholder')}
              aria-labelledby="section-card-notes"
              onChange={(event) => onChange(event.target.value)}
              {...fieldErrorProps(NOTES_ERROR_ID, error)}
            />
            <FieldDescription>{t('ai.notes.help')}</FieldDescription>
            <FieldError id={NOTES_ERROR_ID} message={error} />
          </div>

          <div className="flex flex-wrap items-center justify-between gap-3">
            <Button type="button" variant="ghost" className="w-fit" onClick={close}>
              {t('ai.notes.remove')}
            </Button>
            <p className="text-muted-foreground text-xs">
              {t('ai.notes.length', {
                used: formatNumber(notes.length),
                limit: formatNumber(maxLength),
              })}
            </p>
          </div>
        </div>
      ) : (
        <Button type="button" variant="outline" className="w-fit" onClick={() => setOpen(true)}>
          <PlusIcon aria-hidden />
          {t('ai.notes.add')}
        </Button>
      )}
    </SectionCard>
  )
}
