import { TerminalIcon } from 'lucide-react'
import { useState } from 'react'

import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import { t } from '@/lib/i18n'
import { cn } from '@/lib/utils'

import { schemaFor } from './conditions'
import { unitsOfRequest } from './draft'
import {
  answerLabel,
  fieldTitle,
  guardLabel,
  guardState,
  serviceLabel,
  unitLabel,
} from './labels'
import { PromptText } from './PromptText'
import type { AreaRequest, Catalog, SavedMarkup } from './types'

interface Props {
  /** Los contenedores del pedido, tal como se guardaron: ya limpios y en el orden de la taxonomía. */
  areas: AreaRequest[]
  /** El catálogo, que fija el orden de los campos: el JSON guardado no promete ninguno. */
  catalog: Catalog
  /** Las notas libres del pedido, o vacío. */
  notes: string
  /** El estado de cada guard cuando se pidió. Vacío en un pedido anterior a los guards. */
  guards: Record<string, boolean>
  /** Las marcas del pedido, por la ruta con sesión, o nada si no se dibujó. */
  markup: SavedMarkup | null
  /** La foto sobre la que se marcó, para ver las marcas en su lugar. */
  photoUrl: string | null
  /** El prompt que se mandó. Se abre a pedido: el resumen ya dice lo mismo en menos. */
  prompt: string
  /** Si el rol puede leerlo (R53). Sin esto no llega, y el botón que lo abre tampoco se dibuja. */
  canSeePrompt: boolean
}

/**
 * Lo que se pidió: por área, el servicio y las respuestas por rótulo.
 *
 * Es la respuesta a «¿qué pedí?» mientras se genera y después: sin esto, al
 * plegarse los contenedores la persona se queda sin saber qué está esperando ni
 * qué cambiar si no le gusta. Lo que se muestra sale del pedido y no del estado
 * de la pantalla: es lo que se mandó, aunque después se haya ajustado.
 *
 * El prompt se abre con un botón y no con un colapsable con flecha, porque es
 * una salida, no un pliegue de lo mismo. Sin el rol que puede leerlo, ese botón
 * no está: el prompt tampoco llegó (R53).
 */
export function AnswerSummary({
  areas,
  catalog,
  notes,
  guards,
  markup,
  photoUrl,
  prompt,
  canSeePrompt,
}: Props) {
  const [showPrompt, setShowPrompt] = useState(false)
  // Sólo los activos: listar un guard apagado con la frase de lo que pasa sin él
  // se leía como una regla vigente, y lo que no rigió en el pedido es ruido. Se
  // pide `true` explícito porque un pedido anterior a los guards los trae vacíos,
  // y de ese no se sabe qué rigió.
  const active = catalog.guards.filter((guard) => guards[guard.id] === true)

  return (
    <div className="flex flex-col gap-4">
      {/*
        Sin etiquetas de áreas arriba: cada área encabeza su propio bloque acá
        abajo, así que la fila de badges decía dos veces lo mismo. Y sin línea
        entre el encabezado de la tarjeta y esto: la línea sirve para separar un
        área de la siguiente, que es lo que se confunde al leer de corrido.
      */}
      <div className="flex flex-col gap-5">
        {/*
          Las áreas que se contestaron juntas se leen juntas: el pedido las
          guarda una por una, y listarlas por separado repetiría tres veces el
          mismo bloque de respuestas.
        */}
        {unitsOfRequest(catalog, areas).map((container, index) => {
          const schema = schemaFor(catalog, container.service)
          const fields = schema
            ? schema.fields.filter((field) => container.answers[field.id] !== undefined)
            : []
          const key = container.areas.join('-')
          return (
            <section
              key={key}
              aria-labelledby={`summary-${key}`}
              // Un área debajo de la otra, con una línea entre medio. En dos
              // columnas, áreas de distinto alto dejaban un hueco al lado de la
              // más corta y la tercera arrancaba sola una fila.
              className={cn('flex min-w-0 flex-col gap-2', index > 0 && 'border-t pt-5')}
            >
              <h3 id={`summary-${key}`} className="font-medium">
                {unitLabel(container.areas)}
                <span className="text-muted-foreground font-normal">
                  {' · '}
                  {serviceLabel(container.service)}
                </span>
              </h3>
              {fields.length === 0 ? (
                <p className="text-muted-foreground">{t('ai.summary.noAnswers')}</p>
              ) : null}
              <dl className="grid gap-x-6 gap-y-2 sm:grid-cols-2">
                {fields.map((field) => (
                  <div key={field.id} className="flex min-w-0 flex-col">
                    <dt className="text-muted-foreground text-xs">
                      {fieldTitle(container.service, field.id)}
                    </dt>
                    <dd className="font-medium">
                      {answerLabel(container.service, field.id, container.answers[field.id])}
                    </dd>
                  </div>
                ))}
                {/*
                  El interruptor del área va siempre, encendido o apagado: cambia
                  la línea del prompt de esa sección, y sin verlo acá dos pedidos
                  con las mismas respuestas se leían iguales aunque el modelo
                  recibiera instrucciones distintas.
                */}
                <div className="flex min-w-0 flex-col">
                  <dt className="text-muted-foreground text-xs">
                    {t('ai.containers.wholeArea.title')}
                  </dt>
                  <dd className="font-medium">
                    {container.wholeArea
                      ? t('ai.containers.toggle.yes')
                      : t('ai.containers.toggle.no')}
                  </dd>
                </div>
              </dl>
            </section>
          )
        })}

        {/*
          Las notas al final, con la misma línea que separa un área de la otra:
          son parte de lo que se pidió, y sin ellas el resumen no explicaría por
          qué el resultado hizo algo que ninguna respuesta pide.
        */}
        {notes ? (
          <section
            aria-labelledby="summary-notes"
            className="flex min-w-0 flex-col gap-2 border-t pt-5"
          >
            <h3 id="summary-notes" className="font-medium">
              {t('ai.notes.title')}
            </h3>
            <p className="whitespace-pre-line">{notes}</p>
          </section>
        ) : null}

        {/*
          Las marcas, como se mandaron: la capa sobre la foto, los colores y la
          nota que dice qué significa cada uno. Salen del pedido, no del
          borrador: es lo que viajó, aunque después se haya ajustado.
        */}
        {markup ? (
          <section
            aria-labelledby="summary-markup"
            className="flex min-w-0 flex-col gap-2 border-t pt-5"
          >
            <h3 id="summary-markup" className="font-medium">
              {t('ai.markup.saved.title')}
            </h3>
            <div className="flex flex-col gap-3 sm:flex-row sm:items-start">
              {photoUrl ? (
                <div className="relative w-full shrink-0 sm:w-48">
                  <img
                    src={photoUrl}
                    alt={t('ai.photo.sourceAlt')}
                    className="block w-full rounded-md border"
                  />
                  <img
                    src={markup.image}
                    alt={t('ai.markup.canvas')}
                    className="absolute inset-0 size-full rounded-md opacity-60"
                  />
                </div>
              ) : null}
              <p className="whitespace-pre-line">{markup.note}</p>
            </div>
          </section>
        ) : null}

        {/*
          Los guards que rigieron en el pedido: lo que la IA tenía prohibido
          hacer, aunque las notas lo pidieran.
        */}
        {active.length > 0 ? (
          <section
            aria-labelledby="summary-guards"
            className="flex min-w-0 flex-col gap-2 border-t pt-5"
          >
            <h3 id="summary-guards" className="font-medium">
              {t('ai.guards.title')}
            </h3>
            <dl className="grid gap-x-6 gap-y-2 sm:grid-cols-2">
              {active.map((guard) => (
                <div key={guard.id} className="flex min-w-0 flex-col">
                  <dt className="text-muted-foreground text-xs">{guardLabel(guard.id)}</dt>
                  <dd className="font-medium">{guardState(guard.id, true)}</dd>
                </div>
              ))}
            </dl>
          </section>
        ) : null}
      </div>

      {canSeePrompt ? (
        <>
          <Separator />

          <div className="flex flex-col gap-3">
            <Button
              type="button"
              variant="outline"
              className="w-fit"
              aria-expanded={showPrompt}
              aria-controls="generation-prompt"
              onClick={() => setShowPrompt((current) => !current)}
            >
              <TerminalIcon aria-hidden className="text-primary" />
              {t('ai.summary.output')}
            </Button>
            {showPrompt ? (
              <div id="generation-prompt">
                <PromptText prompt={prompt} />
              </div>
            ) : null}
          </div>
        </>
      ) : null}
    </div>
  )
}
