import React, { useEffect, useMemo, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
import { api, downloadBlob } from '../api'
import { buildPesquisaLink, buildPesquisaRoutePayload, getPesquisaFilterDefaults, hasPesquisaRoutePayload } from '../deepLinks'
import DataTable from './DataTable'
import EquationFormatsPanel from './EquationFormatsPanel'
import LoadingOverlay from './LoadingOverlay'
import MapFrame from './MapFrame'
import ModeloObservacaoCard from './ModeloObservacaoCard'
import ModeloTrabalhosTecnicosPanel from './ModeloTrabalhosTecnicosPanel'
import PlotFigure from './PlotFigure'
import PesquisaAdminConfigPanel from './PesquisaAdminConfigPanel'
import SectionBlock from './SectionBlock'
import ShareLinkButton from './ShareLinkButton'
import SinglePillAutocomplete from './SinglePillAutocomplete'
import { getFaixaDataRecencyInfo } from '../modelRecency'

const EMPTY_FILTERS = {
  nomeModelo: '',
  tipoModelo: '',
  negociacaoModelo: '',
  dataMin: '',
  dataMax: '',
  versionamentoModelos: 'incluir_antigos',
  avalFinalidade: '',
  avalZona: '',
  avalBairro: '',
  avalArea: '',
  avalRh: '',
}

const EMPTY_LOCATION_INPUTS = {
  latitude: '',
  longitude: '',
  logradouro: '',
  numero: '',
  cdlog: '',
}

const CRITERIO_ESPACIAL_OPTIONS = [
  { value: 'maior_distancia', label: 'Maior distância' },
  { value: 'media_distancia', label: 'Média distância' },
  { value: 'menor_distancia', label: 'Menor distância' },
]

const RESULT_INITIAL = {
  modelos: [],
  sugestoes: {},
  total_filtrado: 0,
  total_geral: 0,
}

const PESQUISA_INNER_TABS = [
  { key: 'mapa', label: 'Mapa' },
  { key: 'trabalhos_tecnicos', label: 'Trabalhos Técnicos' },
  { key: 'dados_mercado', label: 'Dados de Mercado' },
  { key: 'metricas', label: 'Métricas' },
  { key: 'transformacoes', label: 'Transformações' },
  { key: 'resumo', label: 'Resumo' },
  { key: 'coeficientes', label: 'Coeficientes' },
  { key: 'obs_calc', label: 'Obs x Calc' },
  { key: 'graficos', label: 'Gráficos' },
]
const MODELO_ABERTO_TRABALHOS_TECNICOS_PADRAO = 'selecionados_e_outras_versoes'

const TIPO_SIGLAS = {
  RECOND: 'Residencia em condominio',
  RCOMD: 'Residencia em condominio',
  TCOND: 'Terreno em condominio',
  SALA: 'Salas comerciais',
  APTO: 'Apartamentos',
  APART: 'Apartamentos',
  AP: 'Apartamentos',
  TERRENO: 'Terrenos',
  TER: 'Terrenos',
  EDIF: 'Edificio',
  RES: 'Residencias isoladas / casas',
  CASA: 'Residencias isoladas / casas',
  LOJA: 'Loja',
  LCOM: 'Loja',
  DEP: 'Deposito',
  DEPOS: 'Deposito',
  CCOM: 'Casa comercial',
}
const TIPOS_MODELO_GENERICOS = [
  'Apartamentos',
  'Casa comercial',
  'Deposito',
  'Edificio',
  'Loja',
  'Salas comerciais',
  'Terrenos',
]

function formatRange(range) {
  if (!range) return '-'
  const min = range.min ?? null
  const max = range.max ?? null
  if (min === null && max === null) return '-'
  if (min !== null && max !== null) return `${formatDateBrIfIso(min)} a ${formatDateBrIfIso(max)}`
  if (min !== null) return `a partir de ${formatDateBrIfIso(min)}`
  return `ate ${formatDateBrIfIso(max)}`
}

function formatCount(value) {
  if (value === null || value === undefined || value === '') return '-'
  if (typeof value === 'number') {
    return new Intl.NumberFormat('pt-BR').format(value)
  }
  return String(value)
}

function formatDistanceKm(value) {
  const number = Number(value)
  if (!Number.isFinite(number)) return '-'
  return `${number.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} km`
}

function formatAvaliandoGeoLabel(index) {
  return `A${index + 1}`
}

function parseCoordinateValue(value) {
  if (value === null || value === undefined) return null
  const text = String(value).trim().replace(',', '.')
  if (!text) return null
  const parsed = Number(text)
  return Number.isFinite(parsed) ? parsed : null
}

function normalizeLogradouroOption(item) {
  if (typeof item === 'string') {
    const text = String(item || '').trim()
    return text ? { value: text, label: text } : null
  }
  if (!item || typeof item !== 'object') return null
  const value = String(item.value ?? item.logradouro ?? '').trim()
  if (!value) return null
  const label = String(item.label ?? item.display_label ?? value).trim() || value
  return {
    value,
    label,
    secondary: String(item.secondary ?? '').trim(),
  }
}

function buildAvaliandosGeoPayload(entries = []) {
  return (entries || []).map((item, index) => ({
    id: String(item?.id || `avaliando-${index + 1}`),
    label: formatAvaliandoGeoLabel(index),
    lat: parseCoordinateValue(item?.lat),
    lon: parseCoordinateValue(item?.lon),
    logradouro: item?.logradouro || null,
    numero_usado: item?.numero_usado || null,
    cdlog: item?.cdlog ?? null,
    origem: item?.origem || null,
  })).filter((item) => item.lat !== null && item.lon !== null)
}

function getResumoEspacialValor(resumo, criterio) {
  if (!resumo || typeof resumo !== 'object') return null
  if (criterio === 'menor_distancia') return Number(resumo.menor_distancia_km)
  if (criterio === 'media_distancia') return Number(resumo.media_distancia_km)
  return Number(resumo.maior_distancia_km)
}

function sortModelosBySpatialCriterion(modelos = [], criterio = 'maior_distancia') {
  if (!Array.isArray(modelos)) return []
  return [...modelos].sort((a, b) => {
    const aValor = getResumoEspacialValor(a?.distancia_resumo, criterio)
    const bValor = getResumoEspacialValor(b?.distancia_resumo, criterio)
    const aSem = !Number.isFinite(aValor)
    const bSem = !Number.isFinite(bValor)
    if (aSem !== bSem) return aSem ? 1 : -1
    if (!aSem && !bSem && aValor !== bValor) return aValor - bValor
    const aNome = String(a?.nome_modelo || a?.arquivo || a?.id || '').toLowerCase()
    const bNome = String(b?.nome_modelo || b?.arquivo || b?.id || '').toLowerCase()
    return aNome.localeCompare(bNome, 'pt-BR')
  })
}

function formatResumoEspacial(resumo) {
  if (!resumo || typeof resumo !== 'object') return '-'
  return `Maior ${String(resumo.maior_distancia_label || '-')} • Média ${String(resumo.media_distancia_label || '-')} • Menor ${String(resumo.menor_distancia_label || '-')}`
}

function formatResumoEspacialCobertura(resumo) {
  if (!resumo || typeof resumo !== 'object') return ''
  const total = Number(resumo.total_avaliandos || 0)
  const comDistancia = Number(resumo.total_com_distancia || 0)
  if (!total) return ''
  return `${comDistancia}/${total} com distância calculada`
}

function formatDistanciasPorAvaliando(distancias = []) {
  if (!Array.isArray(distancias) || !distancias.length) return '-'
  return distancias.map((item, index) => {
    const label = String(item?.label || formatAvaliandoGeoLabel(index)).trim() || formatAvaliandoGeoLabel(index)
    const distancia = String(item?.distancia_label || '').trim() || formatDistanceKm(item?.distancia_km)
    return `${label}: ${distancia}`
  }).join(' • ')
}

function formatLocalizacaoOrigemLabel(localizacao) {
  return localizacao?.origem === 'eixos'
    ? 'Eixos de logradouro'
    : 'Coordenadas informadas'
}

function createLocalizacaoEntry(resolvida, id) {
  return {
    ...resolvida,
    id,
    lat: parseCoordinateValue(resolvida?.lat),
    lon: parseCoordinateValue(resolvida?.lon),
  }
}

function formatDateBrIfIso(value) {
  const text = String(value ?? '').trim()
  if (!text) return '-'
  const isoMatch = text.match(/^(\d{4})-(\d{2})-(\d{2})$/)
  if (!isoMatch) return text
  return `${isoMatch[3]}/${isoMatch[2]}/${isoMatch[1]}`
}

function normalizeTokenText(value) {
  return String(value || '')
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .toUpperCase()
}

function normalizeSearchText(value) {
  return String(value || '')
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .toLowerCase()
    .trim()
}

function splitMultiTerms(value) {
  const text = String(value || '').trim()
  const parts = text.includes('||')
    ? text.split(/\s*\|\|\s*/)
    : text.split(/[;|]/)
  const raw = parts
    .map((item) => String(item || '').trim())
    .filter(Boolean)
  const seen = new Set()
  const unique = []
  raw.forEach((item) => {
    const key = normalizeSearchText(item)
    if (!key || seen.has(key)) return
    seen.add(key)
    unique.push(item)
  })
  return unique
}

function joinMultiTerms(values) {
  return (values || []).map((item) => String(item || '').trim()).filter(Boolean).join(' || ')
}

function sanitizeCompactList(values) {
  const seen = new Set()
  const unique = []
  ;(values || []).forEach((item) => {
    const text = String(item || '').trim()
    const key = normalizeSearchText(text)
    if (!text || !key || seen.has(key)) return
    seen.add(key)
    unique.push(text)
  })
  return unique
}

function uppercaseListText(values) {
  const items = sanitizeCompactList(values)
  return items.map((item) => item.toLocaleUpperCase('pt-BR')).join(', ')
}

function inferDependentVariable(modelo) {
  const equacao = String(modelo?.equacao || '').trim()
  if (!equacao || !equacao.includes('=')) return ''
  return equacao.split('=', 1)[0].trim()
}

function buildVariablesDisplay(modelo) {
  const dependente = inferDependentVariable(modelo)
  const independentes = sanitizeCompactList((modelo?.variaveis_resumo || []).map((item) => item?.variavel))
    .filter((item) => normalizeSearchText(item) !== normalizeSearchText(dependente))
    .filter((item) => normalizeSearchText(item) !== 'const')

  const partes = []
  if (dependente) {
    partes.push(`DEPENDENTE: ${dependente.toLocaleUpperCase('pt-BR')}`)
  }
  if (independentes.length) {
    partes.push(`INDEPENDENTES: ${independentes.map((item) => item.toLocaleUpperCase('pt-BR')).join(', ')}`)
  }
  return partes.join('\n')
}

function buildVariablesContent(text) {
  const lines = String(text || '').split('\n').map((item) => item.trim()).filter(Boolean)
  if (!lines.length) return null

  return (
    <>
      {lines.map((line, index) => {
        const [head, ...rest] = line.split(':')
        const tail = rest.join(':').trim()
        return (
          <span key={`${head}-${index}`} className="pesquisa-card-popover-line">
            <strong>{head}:</strong>{tail ? ` ${tail}` : ''}
          </span>
        )
      })}
    </>
  )
}

function LocalizacaoResumoCard({
  title,
  localizacao = null,
  actions = null,
  className = '',
}) {
  if (!localizacao) return null
  const endereco = String(localizacao?.logradouro || '').trim()
  const numeroUsado = String(localizacao?.numero_usado || '').trim()
  const enderecoTexto = endereco ? `${endereco}${numeroUsado ? `, ${numeroUsado}` : ''}` : ''
  const badges = [
    enderecoTexto ? { label: 'Logradouro', value: enderecoTexto } : null,
    localizacao?.cdlog ? { label: 'CDLOG', value: String(localizacao.cdlog) } : null,
    { label: 'Lat', value: Number(localizacao.lat).toFixed(6) },
    { label: 'Lon', value: Number(localizacao.lon).toFixed(6) },
    { label: 'Origem', value: formatLocalizacaoOrigemLabel(localizacao) },
  ].filter(Boolean)
  const classes = ['pesquisa-localizacao-registered', className].filter(Boolean).join(' ')
  return (
    <div className={classes}>
      <div className="pesquisa-localizacao-registered-head">
        <div className="pesquisa-localizacao-registered-copy">
          <strong>{title}</strong>
          <div className="pesquisa-localizacao-registered-inline-meta">
            {badges.map((item) => (
              <span key={`${title}-${item.label}`} className="pesquisa-localizacao-registered-inline-item">
                <strong>{item.label}:</strong> {item.value}
              </span>
            ))}
          </div>
        </div>
        {actions}
      </div>
    </div>
  )
}

function CompactHoverList({
  label,
  buttonLabel,
  previewText,
  modalText,
  previewContent = null,
  modalContent = null,
}) {
  const rootRef = useRef(null)
  const closePreviewTimeoutRef = useRef(null)
  const panelRef = useRef(null)
  const [previewOpen, setPreviewOpen] = useState(false)
  const [modalOpen, setModalOpen] = useState(false)
  const [previewStyle, setPreviewStyle] = useState({})
  const inlinePreviewText = String(previewText || '').trim()
  const inlineModalText = String(modalText || '').trim()

  function clearPreviewCloseTimeout() {
    if (closePreviewTimeoutRef.current) {
      window.clearTimeout(closePreviewTimeoutRef.current)
      closePreviewTimeoutRef.current = null
    }
  }

  function schedulePreviewClose() {
    clearPreviewCloseTimeout()
    closePreviewTimeoutRef.current = window.setTimeout(() => {
      setPreviewOpen(false)
    }, 80)
  }

  function openPreview() {
    clearPreviewCloseTimeout()
    setPreviewOpen(true)
  }

  function updatePreviewLayout() {
    const bounds = rootRef.current?.getBoundingClientRect()
    const panel = panelRef.current
    if (!bounds || !panel || typeof window === 'undefined') return

    const viewportWidth = window.innerWidth
    const viewportHeight = window.innerHeight
    const gap = 10
    const padding = 16
    const triggerCenter = bounds.left + (bounds.width / 2)
    const towardCenterSide = triggerCenter >= (viewportWidth / 2) ? 'left' : 'right'
    const oppositeSide = towardCenterSide === 'left' ? 'right' : 'left'
    const downwardSpace = viewportHeight - bounds.bottom - gap - padding
    const upwardSpace = bounds.top - gap - padding
    const preferredVertical = downwardSpace >= upwardSpace ? 'down' : 'up'
    const oppositeVertical = preferredVertical === 'down' ? 'up' : 'down'

    const desiredWidth = Math.min(panel.scrollWidth || 560, 560)
    const desiredHeight = Math.min(panel.scrollHeight || 220, 420)

    function clamp(value, min, max) {
      if (max < min) return min
      return Math.min(Math.max(value, min), max)
    }

    function makeVerticalCandidate(side, vertical) {
      const maxWidth = Math.max(160, viewportWidth - (padding * 2))
      const width = Math.min(desiredWidth, maxWidth)
      const maxHeight = Math.max(96, vertical === 'down' ? downwardSpace : upwardSpace)
      const height = Math.min(desiredHeight, maxHeight)
      const leftBase = side === 'left'
        ? bounds.right - width
        : bounds.left
      const left = clamp(leftBase, padding, viewportWidth - padding - width)
      const topBase = vertical === 'down'
        ? bounds.bottom + gap
        : bounds.top - gap - height
      const top = clamp(topBase, padding, viewportHeight - padding - height)
      return {
        left,
        top,
        maxWidth,
        maxHeight,
        score: (Math.min(maxWidth, desiredWidth) / desiredWidth) + (Math.min(maxHeight, desiredHeight) / desiredHeight),
      }
    }

    function makeSideCandidate(side) {
      const maxWidth = Math.max(180, side === 'right'
        ? viewportWidth - bounds.right - gap - padding
        : bounds.left - gap - padding)
      const width = Math.min(desiredWidth, maxWidth)
      const maxHeight = Math.max(120, viewportHeight - (padding * 2))
      const height = Math.min(desiredHeight, maxHeight)
      const leftBase = side === 'right'
        ? bounds.right + gap
        : bounds.left - gap - width
      const left = clamp(leftBase, padding, viewportWidth - padding - width)
      const top = clamp(bounds.top, padding, viewportHeight - padding - height)
      return {
        left,
        top,
        maxWidth,
        maxHeight,
        score: (Math.min(maxWidth, desiredWidth) / desiredWidth) + (Math.min(maxHeight, desiredHeight) / desiredHeight),
      }
    }

    const candidates = [
      makeVerticalCandidate(towardCenterSide, preferredVertical),
      makeVerticalCandidate(towardCenterSide, oppositeVertical),
      makeSideCandidate(towardCenterSide),
      makeSideCandidate(oppositeSide),
      makeVerticalCandidate(oppositeSide, preferredVertical),
      makeVerticalCandidate(oppositeSide, oppositeVertical),
    ]

    const best = candidates.reduce((current, candidate) => {
      if (!current || candidate.score > current.score) return candidate
      return current
    }, null)

    if (!best) return

    setPreviewStyle({
      left: `${best.left}px`,
      top: `${best.top}px`,
      maxWidth: `${Math.max(160, best.maxWidth)}px`,
      maxHeight: `${Math.max(96, best.maxHeight)}px`,
    })
  }

  useEffect(() => {
    if (!previewOpen) return undefined

    const rafId = window.requestAnimationFrame(() => {
      updatePreviewLayout()
    })

    function onWindowResize() {
      updatePreviewLayout()
    }

    window.addEventListener('resize', onWindowResize)
    return () => {
      window.cancelAnimationFrame(rafId)
      window.removeEventListener('resize', onWindowResize)
    }
  }, [previewOpen])

  useEffect(() => () => {
    clearPreviewCloseTimeout()
  }, [])

  useEffect(() => {
    if (!modalOpen) return undefined

    function onDocumentKeyDown(event) {
      if (event.key === 'Escape') {
        setModalOpen(false)
      }
    }

    document.addEventListener('keydown', onDocumentKeyDown)
    return () => {
      document.removeEventListener('keydown', onDocumentKeyDown)
    }
  }, [modalOpen])

  if (!inlineModalText) {
    return (
      <button type="button" className="pesquisa-card-popover-trigger is-empty" disabled>
        {buttonLabel}
      </button>
    )
  }

  return (
    <>
      <span
        ref={rootRef}
        className={`pesquisa-card-popover-wrap${previewOpen ? ' is-open' : ''}`}
        onMouseEnter={() => openPreview()}
        onMouseLeave={() => schedulePreviewClose()}
        onFocus={() => openPreview()}
        onBlur={(event) => {
          if (!rootRef.current?.contains(event.relatedTarget)) {
            setPreviewOpen(false)
          }
        }}
      >
        <button
          type="button"
          className="pesquisa-card-popover-trigger"
          aria-haspopup="dialog"
          aria-expanded={modalOpen}
          aria-label={`${label}. Clique para abrir a lista completa.`}
          onClick={() => {
            setPreviewOpen(false)
            setModalOpen(true)
          }}
        >
          {buttonLabel}
        </button>
      </span>
      {previewOpen && typeof document !== 'undefined'
        ? createPortal(
          <span
            ref={panelRef}
            className="pesquisa-card-popover-panel is-floating"
            role="tooltip"
            aria-label={label}
            style={previewStyle}
            onMouseEnter={() => openPreview()}
            onMouseLeave={() => schedulePreviewClose()}
          >
            <span className="pesquisa-card-popover-preview">{previewContent || inlinePreviewText || inlineModalText}</span>
          </span>,
          document.body,
        )
        : null}
      {modalOpen && typeof document !== 'undefined'
        ? createPortal(
          <div
            className="pesquisa-modal-backdrop"
            role="presentation"
            onClick={() => {
              setModalOpen(false)
            }}
          >
            <div
              className="pesquisa-modal pesquisa-card-values-modal"
              role="dialog"
              aria-modal="true"
              aria-label={label}
              onClick={(event) => event.stopPropagation()}
            >
              <div className="pesquisa-modal-head">
                <h4>{label}</h4>
                <div className="pesquisa-card-values-modal-actions">
                  <button
                    type="button"
                    className="pesquisa-modal-close"
                    onClick={() => {
                      setModalOpen(false)
                    }}
                  >
                    Fechar
                  </button>
                </div>
              </div>
              <div className="pesquisa-modal-body">
                <div className="pesquisa-card-values-content">{modalContent || inlineModalText}</div>
              </div>
            </div>
          </div>,
          document.body,
        )
        : null}
    </>
  )
}

function inferTipoPorNomeModelo(...nomes) {
  const tokens = Object.keys(TIPO_SIGLAS).sort((a, b) => b.length - a.length)
  for (const nome of nomes) {
    const source = normalizeTokenText(nome)
    if (!source) continue
    for (const token of tokens) {
      const re = new RegExp(`(^|[^A-Z])${token}([^A-Z]|$)`)
      if (re.test(source)) {
        return TIPO_SIGLAS[token]
      }
    }
  }
  return ''
}

function formatTipoImovel(modelo) {
  const tipoPorNome = inferTipoPorNomeModelo(modelo?.nome_modelo, modelo?.arquivo)
  if (tipoPorNome) return tipoPorNome

  const text = String(modelo?.tipo_imovel || '').trim()
  if (!text) return '-'

  const mapped = TIPO_SIGLAS[normalizeTokenText(text)]
  return mapped || text
}

function buildApiFilters(filters, avaliandosGeolocalizados = []) {
  const payload = {
    otica: 'avaliando',
    nome: filters.nomeModelo,
    tipo_modelo: filters.tipoModelo,
    negociacao_modelo: filters.negociacaoModelo,
    aval_finalidade: filters.avalFinalidade,
    aval_zona: filters.avalZona,
    aval_bairro: filters.avalBairro,
    data_min: filters.dataMin,
    data_max: filters.dataMax,
    somente_versoes_atuais: filters.versionamentoModelos !== 'incluir_antigos',
    aval_area: filters.avalArea,
    aval_rh: filters.avalRh,
  }
  const avaliandosPayload = buildAvaliandosGeoPayload(avaliandosGeolocalizados)
  if (avaliandosPayload.length > 1) {
    payload.avaliandos_geo_json = JSON.stringify(avaliandosPayload)
  } else if (avaliandosPayload.length === 1) {
    payload.aval_lat = avaliandosPayload[0].lat
    payload.aval_lon = avaliandosPayload[0].lon
  }
  return payload
}

function toInputName(field) {
  let hash = 0
  for (let i = 0; i < field.length; i += 1) {
    hash = (hash * 31 + field.charCodeAt(i)) % 1000000007
  }
  return `mesa_${Math.abs(hash)}`
}

function buildInputAutofillProps(field) {
  return {
    name: toInputName(field),
    autoComplete: 'new-password',
    autoCorrect: 'off',
    autoCapitalize: 'none',
    spellCheck: false,
    'data-lpignore': 'true',
    'data-1p-ignore': 'true',
  }
}

function buildSelectAutofillProps(field) {
  return {
    name: toInputName(field),
    autoComplete: 'new-password',
    'data-lpignore': 'true',
    'data-1p-ignore': 'true',
  }
}

function TextFieldInput({ field, ...props }) {
  return (
    <input
      {...props}
      data-field={field}
      {...buildInputAutofillProps(field)}
    />
  )
}

function NumberFieldInput({ field, ...props }) {
  return (
    <input
      {...props}
      type="number"
      step="any"
      inputMode="decimal"
      data-field={field}
      {...buildInputAutofillProps(field)}
    />
  )
}

function DateFieldInput({ field, ...props }) {
  return (
    <input
      {...props}
      type="date"
      data-field={field}
      {...buildInputAutofillProps(field)}
    />
  )
}

function ChipAutocompleteInput({
  field,
  value,
  onChange,
  placeholder,
  suggestions = [],
  panelTitle = 'Sugestoes',
  loading = false,
  emptyMessage = 'Nenhuma sugestao encontrada.',
  loadingMessage = 'Carregando sugestoes...',
}) {
  const rootRef = useRef(null)
  const [query, setQuery] = useState('')
  const [open, setOpen] = useState(false)
  const [activeIndex, setActiveIndex] = useState(-1)
  const selectedValues = useMemo(() => splitMultiTerms(value), [value])
  const selectedKeys = useMemo(() => new Set(selectedValues.map((item) => normalizeSearchText(item))), [selectedValues])
  const queryNormalized = normalizeSearchText(query)

  useEffect(() => {
    if (!value) setQuery('')
  }, [value])

  const filteredSuggestions = useMemo(() => {
    const unique = []
    const seen = new Set()

    ;(suggestions || []).forEach((item) => {
      const text = String(item || '').trim()
      if (!text) return
      const key = normalizeSearchText(text)
      if (!key || seen.has(key) || selectedKeys.has(key)) return
      seen.add(key)
      unique.push(text)
    })

    if (!queryNormalized) return unique.slice(0, 120)
    return unique
      .filter((item) => normalizeSearchText(item).includes(queryNormalized))
      .slice(0, 120)
  }, [suggestions, queryNormalized, selectedKeys])

  useEffect(() => {
    if (!open) return undefined
    function onDocumentMouseDown(event) {
      if (!rootRef.current) return
      if (!rootRef.current.contains(event.target)) {
        setOpen(false)
      }
    }
    document.addEventListener('mousedown', onDocumentMouseDown)
    return () => document.removeEventListener('mousedown', onDocumentMouseDown)
  }, [open])

  useEffect(() => {
    if (!open || !filteredSuggestions.length) {
      setActiveIndex(-1)
      return
    }
    setActiveIndex(-1)
  }, [filteredSuggestions, open])

  function emitValue(nextValue) {
    onChange({
      target: {
        value: nextValue,
        dataset: { field },
        name: toInputName(field),
      },
    })
  }

  function setSelectedValues(nextSelected) {
    emitValue(joinMultiTerms(nextSelected))
  }

  function addValue(nextValue) {
    const text = String(nextValue || '').trim()
    if (!text) return
    const key = normalizeSearchText(text)
    if (!key || selectedKeys.has(key)) {
      setQuery('')
      return
    }
    setSelectedValues([...selectedValues, text])
    setQuery('')
    setOpen(true)
    setActiveIndex(-1)
  }

  function removeValue(nextValue) {
    const target = String(nextValue || '').trim()
    if (!target) return

    const exactIndex = selectedValues.findIndex((item) => String(item || '').trim() === target)
    if (exactIndex >= 0) {
      const nextSelected = [...selectedValues]
      nextSelected.splice(exactIndex, 1)
      setSelectedValues(nextSelected)
      return
    }

    const key = normalizeSearchText(target)
    const normalizedIndex = selectedValues.findIndex((item) => normalizeSearchText(item) === key)
    if (normalizedIndex < 0) return
    const nextSelected = [...selectedValues]
    nextSelected.splice(normalizedIndex, 1)
    setSelectedValues(nextSelected)
  }

  function onInputChange(event) {
    setQuery(event.target.value)
    setOpen(true)
    setActiveIndex(-1)
  }

  function onInputKeyDown(event) {
    if (event.key === 'Escape') {
      setOpen(false)
      return
    }

    if (!filteredSuggestions.length) return

    if (event.key === 'ArrowDown') {
      event.preventDefault()
      setOpen(true)
      setActiveIndex((prev) => (prev < 0 ? 0 : (prev + 1) % filteredSuggestions.length))
      return
    }

    if (event.key === 'ArrowUp') {
      event.preventDefault()
      setOpen(true)
      setActiveIndex((prev) => {
        if (prev < 0) return filteredSuggestions.length - 1
        return (prev - 1 + filteredSuggestions.length) % filteredSuggestions.length
      })
      return
    }

    if (event.key === 'Enter' && open && activeIndex >= 0) {
      event.preventDefault()
      addValue(filteredSuggestions[activeIndex])
      return
    }

    if (event.key === 'Enter') {
      const next = String(query || '').trim()
      if (next) {
        event.preventDefault()
        addValue(next)
      }
      return
    }

    if (event.key === ',' || event.key === ';' || event.key === '|') {
      const next = String(query || '').trim()
      if (next) {
        event.preventDefault()
        addValue(next)
      }
      return
    }

    if (event.key === 'Backspace' && !query && selectedValues.length) {
      const nextSelected = selectedValues.slice(0, -1)
      setSelectedValues(nextSelected)
    }
  }

  return (
    <div className={`chip-autocomplete${open ? ' is-open' : ''}`} ref={rootRef}>
      {selectedValues.length ? (
        <div className="chip-autocomplete-selected-wrap">
          {selectedValues.map((item) => (
            <span key={`${field}-selected-${item}`} className="chip-autocomplete-selected">
              <span>{item}</span>
              <button
                type="button"
                className="chip-autocomplete-selected-remove"
                onMouseDown={(event) => {
                  event.preventDefault()
                  event.stopPropagation()
                  removeValue(item)
                }}
                onClick={(event) => {
                  event.preventDefault()
                  event.stopPropagation()
                }}
                aria-label={`Remover ${item}`}
              >
                ×
              </button>
            </span>
          ))}
        </div>
      ) : null}

      <TextFieldInput
        field={field}
        value={query}
        onChange={onInputChange}
        onFocus={() => {
          setOpen(true)
          setActiveIndex(-1)
        }}
        onKeyDown={onInputKeyDown}
        placeholder={placeholder}
      />

      {open ? (
        <div className="chip-autocomplete-panel" role="listbox">
          <div className="chip-autocomplete-panel-head">{panelTitle}</div>
          {filteredSuggestions.length ? (
            <div className="chip-autocomplete-chip-wrap">
              {filteredSuggestions.map((item, idx) => (
                <button
                  type="button"
                  key={`${field}-chip-${item}-${idx}`}
                  className={`chip-autocomplete-chip${idx === activeIndex ? ' is-active' : ''}`}
                  onMouseDown={(event) => {
                    event.preventDefault()
                    event.stopPropagation()
                    addValue(item)
                  }}
                >
                  {item}
                </button>
              ))}
            </div>
          ) : loading ? (
            <div className="chip-autocomplete-empty">
              {loadingMessage}
            </div>
          ) : (
            <div className="chip-autocomplete-empty">
              {emptyMessage}
            </div>
          )}
        </div>
      ) : null}
    </div>
  )
}

export default function PesquisaTab({
  sessionId,
  onUsarModeloEmAvaliacao = null,
  onAbrirModeloNoRepositorio = null,
  routeRequest = null,
  scrollToMapaRequest = null,
  onRouteChange = null,
}) {
  const [searchLoading, setSearchLoading] = useState(false)
  const [contextLoading, setContextLoading] = useState(false)
  const [error, setError] = useState('')
  const [pesquisaInicializada, setPesquisaInicializada] = useState(false)
  const [sugestoesInicializadas, setSugestoesInicializadas] = useState(false)
  const [mostrarAdminConfig, setMostrarAdminConfig] = useState(false)
  const [logradouroOptions, setLogradouroOptions] = useState([])
  const [logradouroOptionsLoading, setLogradouroOptionsLoading] = useState(false)
  const [logradouroOptionsLoaded, setLogradouroOptionsLoaded] = useState(false)

  const [filters, setFilters] = useState(EMPTY_FILTERS)
  const [result, setResult] = useState(RESULT_INITIAL)
  const [localizacaoModo, setLocalizacaoModo] = useState('endereco')
  const [localizacaoInputs, setLocalizacaoInputs] = useState(EMPTY_LOCATION_INPUTS)
  const [avaliandosGeolocalizados, setAvaliandosGeolocalizados] = useState([])
  const [localizacaoLoading, setLocalizacaoLoading] = useState(false)
  const [localizacaoError, setLocalizacaoError] = useState('')
  const [localizacaoStatus, setLocalizacaoStatus] = useState('')
  const [criterioEspacial, setCriterioEspacial] = useState('maior_distancia')

  const [selectedIds, setSelectedIds] = useState([])
  const selectAllRef = useRef(null)
  const localizacaoIdCounterRef = useRef(1)

  const [mapaLoading, setMapaLoading] = useState(false)
  const [mapaError, setMapaError] = useState('')
  const [mapaStatus, setMapaStatus] = useState('')
  const [mapaHtmls, setMapaHtmls] = useState({ pontos: '', cobertura: '' })
  const [mapaPayloads, setMapaPayloads] = useState({ pontos: null, cobertura: null })
  const [mapaModoExibicao, setMapaModoExibicao] = useState('pontos')
  const [mapaTrabalhosTecnicosModelosModo, setMapaTrabalhosTecnicosModelosModo] = useState('selecionados_e_outras_versoes')
  const [mapaTrabalhosTecnicosProximidadeModo, setMapaTrabalhosTecnicosProximidadeModo] = useState('sem_proximidade')
  const [mapaTrabalhosTecnicosRaio, setMapaTrabalhosTecnicosRaio] = useState(1000)
  const mapaTrabalhosTecnicosConfigRef = useRef('')

  const [modeloAbertoMeta, setModeloAbertoMeta] = useState(null)
  const [modeloAbertoLoading, setModeloAbertoLoading] = useState(false)
  const [modeloAbertoError, setModeloAbertoError] = useState('')
  const [modeloAbertoActiveTab, setModeloAbertoActiveTab] = useState('mapa')
  const [modeloAbertoDados, setModeloAbertoDados] = useState(null)
  const [modeloAbertoEstatisticas, setModeloAbertoEstatisticas] = useState(null)
  const [modeloAbertoEscalasHtml, setModeloAbertoEscalasHtml] = useState('')
  const [modeloAbertoDadosTransformados, setModeloAbertoDadosTransformados] = useState(null)
  const [modeloAbertoResumoHtml, setModeloAbertoResumoHtml] = useState('')
  const [modeloAbertoEquacoes, setModeloAbertoEquacoes] = useState(null)
  const [modeloAbertoCoeficientes, setModeloAbertoCoeficientes] = useState(null)
  const [modeloAbertoObsCalc, setModeloAbertoObsCalc] = useState(null)
  const [modeloAbertoMapaHtml, setModeloAbertoMapaHtml] = useState('')
  const [modeloAbertoMapaPayload, setModeloAbertoMapaPayload] = useState(null)
  const [modeloAbertoMapaChoices, setModeloAbertoMapaChoices] = useState(['Visualização Padrão'])
  const [modeloAbertoMapaVar, setModeloAbertoMapaVar] = useState('Visualização Padrão')
  const [modeloAbertoTrabalhosTecnicosModelosModo, setModeloAbertoTrabalhosTecnicosModelosModo] = useState(MODELO_ABERTO_TRABALHOS_TECNICOS_PADRAO)
  const [modeloAbertoTrabalhosTecnicos, setModeloAbertoTrabalhosTecnicos] = useState([])
  const [modeloAbertoPlotObsCalc, setModeloAbertoPlotObsCalc] = useState(null)
  const [modeloAbertoPlotResiduos, setModeloAbertoPlotResiduos] = useState(null)
  const [modeloAbertoPlotHistograma, setModeloAbertoPlotHistograma] = useState(null)
  const [modeloAbertoPlotCook, setModeloAbertoPlotCook] = useState(null)
  const [modeloAbertoPlotCorr, setModeloAbertoPlotCorr] = useState(null)
  const [modeloAbertoLoadedTabs, setModeloAbertoLoadedTabs] = useState({})
  const [modeloAbertoLoadingTabs, setModeloAbertoLoadingTabs] = useState({})
  const sectionResultadosRef = useRef(null)
  const sectionMapaRef = useRef(null)
  const scrollMapaHandledRef = useRef('')
  const routeRequestHandledRef = useRef('')
  const resultRequestSeqRef = useRef(0)
  const searchRequestSeqRef = useRef(0)
  const contextRequestSeqRef = useRef(0)
  const modeloAbertoPendingRequestsRef = useRef({})
  const modeloAbertoOpenVersionRef = useRef(0)

  const sugestoes = result.sugestoes || {}
  const opcoesTipoModelo = useMemo(
    () => {
      const atual = String(filters.tipoModelo || '').trim()
      if (!atual || TIPOS_MODELO_GENERICOS.includes(atual)) return TIPOS_MODELO_GENERICOS
      return [...TIPOS_MODELO_GENERICOS, atual]
    },
    [filters.tipoModelo],
  )
  const modoModeloAberto = Boolean(modeloAbertoMeta)
  const avaliandosGeoPayload = useMemo(
    () => buildAvaliandosGeoPayload(avaliandosGeolocalizados),
    [avaliandosGeolocalizados],
  )
  const localizacaoAtiva = avaliandosGeoPayload.length > 0
  const localizacaoMultipla = avaliandosGeoPayload.length > 1
  const avaliandoUnicoAtivo = avaliandosGeoPayload.length === 1
  const modelosOrdenados = useMemo(
    () => (localizacaoMultipla ? sortModelosBySpatialCriterion(result.modelos || [], criterioEspacial) : (result.modelos || [])),
    [criterioEspacial, localizacaoMultipla, result.modelos],
  )
  const resultIds = useMemo(() => modelosOrdenados.map((modelo) => modelo.id), [modelosOrdenados])
  const todosSelecionados = resultIds.length > 0 && resultIds.every((id) => selectedIds.includes(id))
  const algunsSelecionados = resultIds.some((id) => selectedIds.includes(id))
  const mapaHtmlAtual = mapaHtmls[mapaModoExibicao] || ''
  const mapaPayloadAtual = mapaPayloads[mapaModoExibicao] || null
  const mapaFoiGerado = Boolean(mapaHtmls.pontos || mapaHtmls.cobertura || mapaPayloads.pontos || mapaPayloads.cobertura)
  const pesquisaShareAvaliando = !localizacaoMultipla ? (avaliandosGeoPayload[0] || null) : null
  const pesquisaShareHref = buildPesquisaLink(filters, pesquisaShareAvaliando)
  const pesquisaShareDisabled = localizacaoMultipla
  const isPesquisaBusy = searchLoading

  function buildPesquisaReturnIntent() {
    return {
      ...buildPesquisaRoutePayload(filters, pesquisaShareAvaliando),
      pesquisaExecutada: true,
      avaliandos: avaliandosGeolocalizados.map((item, index) => ({
        id: String(item?.id || `avaliando-${index + 1}`),
        lat: parseCoordinateValue(item?.lat),
        lon: parseCoordinateValue(item?.lon),
        logradouro: String(item?.logradouro || ''),
        numero_usado: String(item?.numero_usado || ''),
        cdlog: item?.cdlog ?? null,
        origem: String(item?.origem || 'coords'),
      })).filter((item) => item.lat !== null && item.lon !== null),
    }
  }

  function emitPesquisaRoute(nextFilters = filters, nextAvaliandos = avaliandosGeolocalizados) {
    if (typeof onRouteChange !== 'function') return
    const avaliandosPayload = buildAvaliandosGeoPayload(nextAvaliandos)
    const avaliando = avaliandosPayload.length === 1 ? avaliandosPayload[0] : null
    onRouteChange(buildPesquisaRoutePayload(nextFilters, avaliando))
  }

  function scrollToElementTop(el, behavior = 'smooth', offsetPx = 0) {
    if (!el || typeof window === 'undefined') return
    const rect = el.getBoundingClientRect()
    const targetTop = Math.max(0, window.scrollY + rect.top - offsetPx)
    window.scrollTo({ top: targetTop, behavior })
  }

  function scrollParaTopoDaPagina() {
    if (typeof window === 'undefined') return
    window.scrollTo({ top: 0, behavior: 'smooth' })
  }

  function scrollParaResultadosNoTopo() {
    window.requestAnimationFrame(() => {
      window.requestAnimationFrame(() => {
        scrollToElementTop(sectionResultadosRef.current, 'smooth', 0)
      })
    })
  }

  function resetMapaPesquisa() {
    setMapaHtmls({ pontos: '', cobertura: '' })
    setMapaPayloads({ pontos: null, cobertura: null })
    setMapaStatus('')
    setMapaError('')
    setMapaModoExibicao('pontos')
    mapaTrabalhosTecnicosConfigRef.current = ''
  }

  function getMapaTrabalhosTecnicosRequestConfig(overrides = {}) {
    const modelosModoBruto = overrides.trabalhosTecnicosModelosModo ?? mapaTrabalhosTecnicosModelosModo
    const modelosModo = String(modelosModoBruto || 'selecionados') === 'selecionados_e_anteriores'
      ? 'selecionados_e_outras_versoes'
      : String(modelosModoBruto || 'selecionados')
    const proximidadeModoBruto = overrides.trabalhosTecnicosProximidadeModo ?? mapaTrabalhosTecnicosProximidadeModo
    const proximidadeModo = localizacaoAtiva ? String(proximidadeModoBruto || 'sem_proximidade') : 'sem_proximidade'
    const raioNumero = Number(overrides.trabalhosTecnicosRaio ?? mapaTrabalhosTecnicosRaio)
    const raio = Number.isFinite(raioNumero)
      ? Math.max(0, Math.min(5000, Math.round(raioNumero)))
      : 1000
    return { modelosModo, proximidadeModo, raio }
  }

  function buildMapaTrabalhosTecnicosConfigKey(config) {
    return JSON.stringify({
      totalAvaliandos: avaliandosGeoPayload.length,
      modelosModo: config.modelosModo,
      proximidadeModo: config.proximidadeModo,
      criterioEspacial: localizacaoMultipla ? criterioEspacial : null,
      raio: config.proximidadeModo === 'proximos_ao_avaliando' ? config.raio : null,
    })
  }

  async function carregarMapaPesquisa(ids, overrides = {}) {
    const idsValidos = (ids || []).map((item) => String(item || '').trim()).filter(Boolean)
    const modoExibicaoSolicitado = String(overrides.modoExibicao || mapaModoExibicao || 'pontos')
    const trabalhosTecnicosConfig = getMapaTrabalhosTecnicosRequestConfig(overrides)

    if (!idsValidos.length) {
      setMapaHtmls({ pontos: '', cobertura: '' })
      setMapaPayloads({ pontos: null, cobertura: null })
      setMapaStatus('Nenhum modelo marcado para exibição no mapa.')
      setMapaError('')
      mapaTrabalhosTecnicosConfigRef.current = ''
      return
    }

    setMapaLoading(true)
    setMapaError('')
    try {
      const response = await api.pesquisarMapaModelos(
        idsValidos,
        localizacaoMultipla ? avaliandosGeoPayload : (avaliandosGeoPayload[0] || null),
        modoExibicaoSolicitado,
        criterioEspacial,
        trabalhosTecnicosConfig.modelosModo,
        trabalhosTecnicosConfig.proximidadeModo,
        trabalhosTecnicosConfig.raio,
      )
      const mapaHtmlSolicitado = String(
        response.mapa_html
          || (modoExibicaoSolicitado === 'cobertura' ? response.mapa_html_cobertura : response.mapa_html_pontos)
          || '',
      )
      const mapaPayloadSolicitado = response.mapa_payload
        || (modoExibicaoSolicitado === 'cobertura' ? response.mapa_payload_cobertura : response.mapa_payload_pontos)
        || null
      setMapaHtmls({
        pontos: modoExibicaoSolicitado === 'pontos' ? mapaHtmlSolicitado : '',
        cobertura: modoExibicaoSolicitado === 'cobertura' ? mapaHtmlSolicitado : '',
      })
      setMapaPayloads({
        pontos: modoExibicaoSolicitado === 'pontos' ? mapaPayloadSolicitado : null,
        cobertura: modoExibicaoSolicitado === 'cobertura' ? mapaPayloadSolicitado : null,
      })
      setMapaStatus(response.status || '')
      mapaTrabalhosTecnicosConfigRef.current = buildMapaTrabalhosTecnicosConfigKey(trabalhosTecnicosConfig)
    } catch (err) {
      setMapaError(err.message)
    } finally {
      setMapaLoading(false)
    }
  }

  async function buscarModelos(nextFilters = filters, nextAvaliandos = avaliandosGeolocalizados, options = {}) {
    const requestId = resultRequestSeqRef.current + 1
    const searchRequestId = searchRequestSeqRef.current + 1
    resultRequestSeqRef.current = requestId
    searchRequestSeqRef.current = searchRequestId
    setSearchLoading(true)
    setError('')
    try {
      const response = await api.pesquisarModelos(buildApiFilters(nextFilters, nextAvaliandos))
      if (requestId !== resultRequestSeqRef.current) return
      const modelos = response.modelos || []
      const idsNovos = new Set(modelos.map((item) => item.id))

      setResult({
        ...RESULT_INITIAL,
        ...response,
        modelos,
        sugestoes: response.sugestoes || {},
      })

      setSelectedIds((current) => current.filter((id) => idsNovos.has(id)))

      resetMapaPesquisa()
      setPesquisaInicializada(true)
      setSugestoesInicializadas(true)
      if (options.syncRoute !== false) {
        emitPesquisaRoute(nextFilters, nextAvaliandos)
      }
    } catch (err) {
      if (requestId !== resultRequestSeqRef.current) return
      setError(err.message)
    } finally {
      if (searchRequestId === searchRequestSeqRef.current) {
        setSearchLoading(false)
      }
    }
  }

  async function carregarContextoInicial(options = {}) {
    const requestId = resultRequestSeqRef.current + 1
    const contextRequestId = contextRequestSeqRef.current + 1
    resultRequestSeqRef.current = requestId
    contextRequestSeqRef.current = contextRequestId
    setContextLoading(true)
    setError('')
    try {
      const response = await api.pesquisarModelos({ somente_contexto: true })
      if (requestId !== resultRequestSeqRef.current) return

      setResult({
        ...RESULT_INITIAL,
        ...response,
        modelos: [],
        sugestoes: response.sugestoes || {},
      })
      setSelectedIds([])
      resetMapaPesquisa()
      setPesquisaInicializada(false)
      setSugestoesInicializadas(true)
      if (options.syncRoute) {
        emitPesquisaRoute(options.filters || getPesquisaFilterDefaults(), options.avaliandos || avaliandosGeolocalizados)
      }
    } catch (err) {
      if (requestId !== resultRequestSeqRef.current) return
      setError(err.message)
      setSugestoesInicializadas(true)
    } finally {
      if (contextRequestId === contextRequestSeqRef.current) {
        setContextLoading(false)
      }
    }
  }

  async function carregarSugestoesLogradouro() {
    if (logradouroOptionsLoading || logradouroOptionsLoaded) return
    setLogradouroOptionsLoading(true)
    try {
      const response = await api.pesquisarLogradourosEixos()
      const opcoes = Array.isArray(response?.logradouros_eixos)
        ? response.logradouros_eixos.map(normalizeLogradouroOption).filter(Boolean)
        : []
      setLogradouroOptions(opcoes)
      setLogradouroOptionsLoaded(true)
    } catch (_err) {
      setLogradouroOptions([])
    } finally {
      setLogradouroOptionsLoading(false)
    }
  }

  useEffect(() => {
    const requestKey = String(routeRequest?.requestKey || '').trim()
    if (requestKey) return undefined
    void carregarContextoInicial()
    return undefined
  }, [routeRequest])

  useEffect(() => {
    const requestKey = String(routeRequest?.requestKey || '').trim()
    if (!requestKey) return
    if (routeRequestHandledRef.current === requestKey) return
    routeRequestHandledRef.current = requestKey

    const nextFilters = {
      ...getPesquisaFilterDefaults(),
      ...(routeRequest?.filters || {}),
    }
    const rawAvaliandos = Array.isArray(routeRequest?.avaliandos) ? routeRequest.avaliandos : []
    let nextEntries = rawAvaliandos
      .map((item, index) => {
        const lat = parseCoordinateValue(item?.lat)
        const lon = parseCoordinateValue(item?.lon)
        if (lat === null || lon === null) return null
        return createLocalizacaoEntry({
          lat,
          lon,
          origem: String(item?.origem || 'coords'),
          logradouro: String(item?.logradouro || ''),
          numero_usado: String(item?.numero_usado || ''),
          cdlog: item?.cdlog ?? null,
        }, String(item?.id || `avaliando-${localizacaoIdCounterRef.current + index}`))
      })
      .filter(Boolean)
    const lat = parseCoordinateValue(routeRequest?.avaliando?.lat)
    const lon = parseCoordinateValue(routeRequest?.avaliando?.lon)
    const possuiAvaliando = lat !== null && lon !== null
    if (!nextEntries.length && possuiAvaliando) {
      nextEntries = [createLocalizacaoEntry({
        lat,
        lon,
        origem: 'coords',
        logradouro: '',
        numero_usado: '',
        cdlog: null,
      }, `avaliando-${localizacaoIdCounterRef.current}`)]
      localizacaoIdCounterRef.current += 1
    } else if (nextEntries.length) {
      localizacaoIdCounterRef.current += nextEntries.length
    }

    setFilters(nextFilters)
    setAvaliandosGeolocalizados(nextEntries)
    setLocalizacaoModo(possuiAvaliando ? 'coords' : 'endereco')
    setLocalizacaoInputs(EMPTY_LOCATION_INPUTS)
    setLocalizacaoError('')
    setLocalizacaoStatus('')
    resetMapaPesquisa()

    if (routeRequest?.pesquisaExecutada || hasPesquisaRoutePayload(nextFilters, routeRequest?.avaliando) || nextEntries.length > 1) {
      void buscarModelos(nextFilters, nextEntries, { syncRoute: false })
      return
    }

    void carregarContextoInicial({ syncRoute: false, filters: nextFilters, avaliandos: nextEntries })
  }, [routeRequest])

  useEffect(() => {
    if (!selectAllRef.current) return
    selectAllRef.current.indeterminate = algunsSelecionados && !todosSelecionados
  }, [algunsSelecionados, todosSelecionados])

  useEffect(() => {
    const requestKey = String(scrollToMapaRequest?.requestKey || '').trim()
    if (!requestKey) return
    if (scrollMapaHandledRef.current === requestKey) return
    scrollMapaHandledRef.current = requestKey

    window.requestAnimationFrame(() => {
      window.requestAnimationFrame(() => {
        scrollToElementTop(sectionMapaRef.current, 'smooth', 0)
      })
    })
  }, [scrollToMapaRequest])

  useEffect(() => {
    if (!mapaFoiGerado || !localizacaoAtiva || mapaLoading) return undefined
    const trabalhosTecnicosConfig = getMapaTrabalhosTecnicosRequestConfig()
    const nextKey = buildMapaTrabalhosTecnicosConfigKey(trabalhosTecnicosConfig)
    if (nextKey === mapaTrabalhosTecnicosConfigRef.current) return undefined

    const timeoutId = window.setTimeout(() => {
      void carregarMapaPesquisa(selectedIds)
    }, 220)

    return () => {
      window.clearTimeout(timeoutId)
    }
  }, [
    localizacaoAtiva,
    localizacaoMultipla,
    mapaFoiGerado,
    mapaLoading,
    mapaTrabalhosTecnicosModelosModo,
    mapaTrabalhosTecnicosProximidadeModo,
    mapaTrabalhosTecnicosRaio,
    avaliandosGeoPayload.length,
    criterioEspacial,
  ])

  function onFieldChange(event) {
    const { value, checked, type, dataset, name } = event.target
    const field = dataset.field || name
    if (!field) return
    setFilters((prev) => ({ ...prev, [field]: type === 'checkbox' ? checked : value }))
  }

  function onLocalizacaoFieldChange(event) {
    const { value, dataset, name } = event.target
    const field = dataset.field || name
    if (!field) return
    atualizarCampoLocalizacao(field, value)
  }

  function atualizarCampoLocalizacao(field, value) {
    if (!field) return
    setLocalizacaoInputs((prev) => ({ ...prev, [field]: value }))
    setLocalizacaoError('')
  }

  async function onLimparFiltros() {
    const nextFilters = getPesquisaFilterDefaults()
    setFilters(nextFilters)
    await carregarContextoInicial({
      syncRoute: true,
      filters: nextFilters,
      avaliandos: avaliandosGeolocalizados,
    })
  }

  function onToggleSelecionado(modelId) {
    setSelectedIds((current) => {
      if (current.includes(modelId)) {
        return current.filter((id) => id !== modelId)
      }
      return [...current, modelId]
    })
  }

  function onToggleSelecionarTodos() {
    setSelectedIds((current) => {
      if (todosSelecionados) {
        const idsAtuais = new Set(resultIds)
        return current.filter((id) => !idsAtuais.has(id))
      }
      const next = new Set(current)
      resultIds.forEach((id) => next.add(id))
      return Array.from(next)
    })
  }

  function onUsarEmAvaliacao(modelo) {
    if (!sessionId) {
      setError('Sessao indisponivel no momento. Aguarde e tente novamente.')
      return
    }
    if (typeof onUsarModeloEmAvaliacao === 'function') {
      onUsarModeloEmAvaliacao(modelo)
    }
  }

  function limparConteudoModeloAberto() {
    modeloAbertoPendingRequestsRef.current = {}
    setModeloAbertoDados(null)
    setModeloAbertoEstatisticas(null)
    setModeloAbertoEscalasHtml('')
    setModeloAbertoDadosTransformados(null)
    setModeloAbertoResumoHtml('')
    setModeloAbertoEquacoes(null)
    setModeloAbertoCoeficientes(null)
    setModeloAbertoObsCalc(null)
    setModeloAbertoMapaHtml('')
    setModeloAbertoMapaPayload(null)
    setModeloAbertoMapaChoices(['Visualização Padrão'])
    setModeloAbertoMapaVar('Visualização Padrão')
    setModeloAbertoTrabalhosTecnicosModelosModo(MODELO_ABERTO_TRABALHOS_TECNICOS_PADRAO)
    setModeloAbertoTrabalhosTecnicos([])
    setModeloAbertoPlotObsCalc(null)
    setModeloAbertoPlotResiduos(null)
    setModeloAbertoPlotHistograma(null)
    setModeloAbertoPlotCook(null)
    setModeloAbertoPlotCorr(null)
    setModeloAbertoLoadedTabs({})
    setModeloAbertoLoadingTabs({})
  }

  function aplicarSecaoModeloAberto(secao, resp) {
    const key = String(secao || '').trim()
    if (key === 'dados_mercado') {
      setModeloAbertoDados(resp?.dados || null)
      return
    }
    if (key === 'metricas') {
      setModeloAbertoEstatisticas(resp?.estatisticas || null)
      return
    }
    if (key === 'transformacoes') {
      setModeloAbertoEscalasHtml(resp?.escalas_html || '')
      setModeloAbertoDadosTransformados(resp?.dados_transformados || null)
      return
    }
    if (key === 'resumo') {
      setModeloAbertoResumoHtml(resp?.resumo_html || '')
      setModeloAbertoEquacoes(resp?.equacoes || null)
      return
    }
    if (key === 'coeficientes') {
      setModeloAbertoCoeficientes(resp?.coeficientes || null)
      return
    }
    if (key === 'obs_calc') {
      setModeloAbertoObsCalc(resp?.obs_calc || null)
      return
    }
    if (key === 'graficos') {
      setModeloAbertoPlotObsCalc(resp?.grafico_obs_calc || null)
      setModeloAbertoPlotResiduos(resp?.grafico_residuos || null)
      setModeloAbertoPlotHistograma(resp?.grafico_histograma || null)
      setModeloAbertoPlotCook(resp?.grafico_cook || null)
      setModeloAbertoPlotCorr(resp?.grafico_correlacao || null)
      return
    }
    if (key === 'trabalhos_tecnicos') {
      setModeloAbertoTrabalhosTecnicos(Array.isArray(resp?.trabalhos_tecnicos) ? resp.trabalhos_tecnicos : [])
      setModeloAbertoTrabalhosTecnicosModelosModo(resp?.trabalhos_tecnicos_modelos_modo || MODELO_ABERTO_TRABALHOS_TECNICOS_PADRAO)
      return
    }
    if (key === 'mapa') {
      const nextChoices = Array.isArray(resp?.mapa_choices) && resp.mapa_choices.length
        ? resp.mapa_choices
        : ['Visualização Padrão']
      setModeloAbertoMapaHtml(resp?.mapa_html || '')
      setModeloAbertoMapaPayload(resp?.mapa_payload || null)
      setModeloAbertoMapaChoices(nextChoices)
      setModeloAbertoMapaVar((current) => (nextChoices.includes(current) ? current : 'Visualização Padrão'))
      setModeloAbertoTrabalhosTecnicos(Array.isArray(resp?.trabalhos_tecnicos) ? resp.trabalhos_tecnicos : [])
      setModeloAbertoTrabalhosTecnicosModelosModo(resp?.trabalhos_tecnicos_modelos_modo || MODELO_ABERTO_TRABALHOS_TECNICOS_PADRAO)
    }
  }

  async function garantirSecaoModeloAberto(secao, options = {}) {
    const secaoNormalizada = String(secao || '').trim()
    if (!sessionId || !secaoNormalizada) return
    if (!options.force && modeloAbertoLoadedTabs[secaoNormalizada]) return
    if (modeloAbertoPendingRequestsRef.current[secaoNormalizada]) {
      await modeloAbertoPendingRequestsRef.current[secaoNormalizada]
      return
    }

    const expectedVersion = options.expectedVersion ?? modeloAbertoOpenVersionRef.current
    const trabalhosTecnicosModo = options.trabalhosTecnicosModelosModo || modeloAbertoTrabalhosTecnicosModelosModo
    setModeloAbertoLoadingTabs((prev) => ({ ...prev, [secaoNormalizada]: true }))

    const request = (async () => {
      try {
        const resp = await api.visualizacaoSection(sessionId, secaoNormalizada, trabalhosTecnicosModo)
        if (modeloAbertoOpenVersionRef.current !== expectedVersion) return
        aplicarSecaoModeloAberto(secaoNormalizada, resp)
        setModeloAbertoLoadedTabs((prev) => ({
          ...prev,
          [secaoNormalizada]: true,
          ...(secaoNormalizada === 'mapa' ? { trabalhos_tecnicos: true } : {}),
        }))
      } catch (err) {
        if (modeloAbertoOpenVersionRef.current !== expectedVersion) return
        setModeloAbertoError(err.message || 'Falha ao abrir modelo.')
      } finally {
        if (modeloAbertoOpenVersionRef.current !== expectedVersion) return
        setModeloAbertoLoadingTabs((prev) => ({ ...prev, [secaoNormalizada]: false }))
      }
    })()

    modeloAbertoPendingRequestsRef.current[secaoNormalizada] = request
    try {
      await request
    } finally {
      if (modeloAbertoPendingRequestsRef.current[secaoNormalizada] === request) {
        delete modeloAbertoPendingRequestsRef.current[secaoNormalizada]
      }
    }
  }

  async function onAbrirModelo(modelo) {
    if (typeof onAbrirModeloNoRepositorio === 'function') {
      onAbrirModeloNoRepositorio({
        ...modelo,
        returnIntent: buildPesquisaReturnIntent(),
      })
      return
    }

    if (!sessionId) {
      setError('Sessao indisponivel no momento. Aguarde e tente novamente.')
      return
    }
    modeloAbertoOpenVersionRef.current += 1
    const openVersion = modeloAbertoOpenVersionRef.current
    limparConteudoModeloAberto()
    setModeloAbertoLoading(true)
    setModeloAbertoError('')
    setModeloAbertoMeta({
      id: modelo.id,
      nome: modelo.nome_modelo || modelo.arquivo || modelo.id,
      observacao: '',
    })
    try {
      const resp = await api.visualizacaoRepositorioCarregar(sessionId, modelo.id)
      if (modeloAbertoOpenVersionRef.current !== openVersion) return
      setModeloAbertoActiveTab('mapa')
      setModeloAbertoMeta({
        id: modelo.id,
        nome: modelo.nome_modelo || modelo.arquivo || modelo.id,
        observacao: String(resp?.observacao_modelo || '').trim(),
      })
      await garantirSecaoModeloAberto('mapa', {
        force: true,
        expectedVersion: openVersion,
        trabalhosTecnicosModelosModo: MODELO_ABERTO_TRABALHOS_TECNICOS_PADRAO,
      })
      window.requestAnimationFrame(() => {
        scrollParaTopoDaPagina()
      })
    } catch (err) {
      setModeloAbertoError(err.message || 'Falha ao abrir modelo.')
    } finally {
      setModeloAbertoLoading(false)
    }
  }

  function onVoltarPesquisa() {
    modeloAbertoOpenVersionRef.current += 1
    setModeloAbertoMeta(null)
    setModeloAbertoError('')
    setModeloAbertoActiveTab('mapa')
    setModeloAbertoLoading(false)
    limparConteudoModeloAberto()
    scrollParaResultadosNoTopo()
  }

  async function atualizarMapaModeloAberto(
    nextVar = modeloAbertoMapaVar,
    nextTrabalhosTecnicosModo = modeloAbertoTrabalhosTecnicosModelosModo,
  ) {
    if (!sessionId) return
    setModeloAbertoLoadingTabs((prev) => ({ ...prev, mapa: true }))
    try {
      const resp = await api.updateVisualizacaoMap(sessionId, nextVar, nextTrabalhosTecnicosModo)
      setModeloAbertoMapaHtml(resp?.mapa_html || '')
      setModeloAbertoMapaPayload(resp?.mapa_payload || null)
      setModeloAbertoTrabalhosTecnicos(Array.isArray(resp?.trabalhos_tecnicos) ? resp.trabalhos_tecnicos : [])
      setModeloAbertoTrabalhosTecnicosModelosModo(resp?.trabalhos_tecnicos_modelos_modo || nextTrabalhosTecnicosModo)
      setModeloAbertoLoadedTabs((prev) => ({ ...prev, mapa: true, trabalhos_tecnicos: true }))
    } finally {
      setModeloAbertoLoadingTabs((prev) => ({ ...prev, mapa: false }))
    }
  }

  async function onModeloAbertoMapChange(nextVar) {
    setModeloAbertoMapaVar(nextVar)
    try {
      await atualizarMapaModeloAberto(nextVar, modeloAbertoTrabalhosTecnicosModelosModo)
    } catch (err) {
      setModeloAbertoError(err.message || 'Falha ao atualizar mapa do modelo.')
    }
  }

  async function onModeloAbertoTrabalhosTecnicosModeChange(nextMode) {
    setModeloAbertoTrabalhosTecnicosModelosModo(nextMode)
    try {
      await atualizarMapaModeloAberto(modeloAbertoMapaVar, nextMode)
    } catch (err) {
      setModeloAbertoError(err.message || 'Falha ao atualizar mapa do modelo.')
    }
  }

  async function onDownloadEquacaoModeloAberto(mode) {
    if (!sessionId || !mode) return
    setModeloAbertoLoading(true)
    try {
      const blob = await api.exportEquationViz(sessionId, mode)
      const sufixo = String(mode) === 'excel_sab' ? 'estilo_sab' : 'excel'
      downloadBlob(blob, `equacao_modelo_${sufixo}.xlsx`)
    } catch (err) {
      setModeloAbertoError(err.message || 'Falha ao exportar equação.')
    } finally {
      setModeloAbertoLoading(false)
    }
  }

  function onModeloAbertoTabSelect(nextTab) {
    setModeloAbertoActiveTab(nextTab)
    void garantirSecaoModeloAberto(nextTab)
  }

  async function onGerarMapaSelecionados() {
    if (!selectedIds.length) {
      setMapaError('Selecione ao menos um modelo para plotar no mapa.')
      return
    }

    await carregarMapaPesquisa(selectedIds)
  }

  function onMapaModoExibicaoChange(event) {
    const nextModo = String(event?.target?.value || 'pontos')
    setMapaModoExibicao(nextModo)
    if (!mapaFoiGerado || mapaLoading || !selectedIds.length || mapaHtmls[nextModo] || mapaPayloads[nextModo]) return
    void carregarMapaPesquisa(selectedIds, { modoExibicao: nextModo })
  }

  async function onAdminConfigSalva() {
    if (pesquisaInicializada) {
      await buscarModelos(filters, avaliandosGeolocalizados)
      return
    }
    await carregarContextoInicial()
  }

  function onLimparFormularioLocalizacao() {
    setLocalizacaoInputs(EMPTY_LOCATION_INPUTS)
    setLocalizacaoModo('endereco')
    setLocalizacaoError('')
    setLocalizacaoStatus('')
  }

  async function atualizarPesquisaAposGeolocalizacao(nextEntries) {
    resetMapaPesquisa()
    if (pesquisaInicializada) {
      await buscarModelos(filters, nextEntries)
    }
  }

  async function onResolverLocalizacao() {
    setLocalizacaoError('')
    setLocalizacaoStatus('')
    if (localizacaoModo === 'coords') {
      const lat = Number(localizacaoInputs.latitude)
      const lon = Number(localizacaoInputs.longitude)
      if (!Number.isFinite(lat) || !Number.isFinite(lon)) {
        setLocalizacaoError('Informe latitude e longitude válidas para localizar o avaliando.')
        return
      }
    } else {
      const logradouro = String(localizacaoInputs.logradouro || '').trim()
      const cdlogTexto = String(localizacaoInputs.cdlog || '').trim()
      const cdlog = cdlogTexto ? Number(cdlogTexto) : null
      if (!logradouro && !(Number.isFinite(cdlog) && cdlog > 0)) {
        setLocalizacaoError('Informe o logradouro ou um CDLOG válido para localizar o avaliando.')
        return
      }
      if (cdlogTexto && !(Number.isFinite(cdlog) && cdlog > 0)) {
        setLocalizacaoError('Informe um CDLOG válido para localizar o avaliando.')
        return
      }
      const numero = Number(localizacaoInputs.numero)
      if (!Number.isFinite(numero) || numero <= 0) {
        setLocalizacaoError('Informe um número válido para localizar o avaliando.')
        return
      }
    }

    setLocalizacaoLoading(true)
    try {
      const response = await api.pesquisarLocalizacaoAvaliando({
        latitude: localizacaoModo === 'coords' ? Number(localizacaoInputs.latitude) : null,
        longitude: localizacaoModo === 'coords' ? Number(localizacaoInputs.longitude) : null,
        logradouro: localizacaoModo === 'endereco' ? String(localizacaoInputs.logradouro || '').trim() : null,
        numero: localizacaoModo === 'endereco' ? Number(localizacaoInputs.numero) : null,
        cdlog: localizacaoModo === 'endereco' && String(localizacaoInputs.cdlog || '').trim()
          ? Number(localizacaoInputs.cdlog)
          : null,
      })
      const resolvida = {
        ...response,
        lat: parseCoordinateValue(response?.lat),
        lon: parseCoordinateValue(response?.lon),
      }
      const nextEntry = createLocalizacaoEntry(
        resolvida,
        `avaliando-${localizacaoIdCounterRef.current}`,
      )
      localizacaoIdCounterRef.current += 1
      const nextEntries = [...avaliandosGeolocalizados, nextEntry]
      setAvaliandosGeolocalizados(nextEntries)
      setLocalizacaoInputs(EMPTY_LOCATION_INPUTS)
      setLocalizacaoStatus(
        nextEntries.length > 1
          ? `${nextEntries.length} avaliandos geolocalizados com sucesso.`
          : (response?.status || 'Geolocalização do avaliando registrada.')
      )
      await atualizarPesquisaAposGeolocalizacao(nextEntries)
    } catch (err) {
      setLocalizacaoError(err.message || 'Falha ao localizar o avaliando.')
    } finally {
      setLocalizacaoLoading(false)
    }
  }
  async function onRemoverAvaliandoLocalizacao(id) {
    const nextEntries = avaliandosGeolocalizados.filter((item) => item.id !== id)
    setAvaliandosGeolocalizados(nextEntries)
    setLocalizacaoError('')
    setLocalizacaoStatus('')
    await atualizarPesquisaAposGeolocalizacao(nextEntries)
  }

  if (modoModeloAberto) {
    return (
      <div className="tab-content">
        <div className="pesquisa-opened-model-view">
          <div className="pesquisa-opened-model-head">
            <div className="pesquisa-opened-model-title-wrap">
              <h3>{modeloAbertoMeta?.nome || 'Modelo'}</h3>
            </div>
            <button
              type="button"
              className="model-source-back-btn model-source-back-btn-danger"
              onClick={onVoltarPesquisa}
              disabled={modeloAbertoLoading}
            >
              Voltar para pesquisa
            </button>
          </div>
          <ModeloObservacaoCard text={modeloAbertoMeta?.observacao} className="pesquisa-opened-model-observacao" />

          <div className="inner-tabs" role="tablist" aria-label="Abas internas do modelo aberto na pesquisa">
            {PESQUISA_INNER_TABS.map((tab) => (
              <button
                key={tab.key}
                type="button"
                className={modeloAbertoActiveTab === tab.key ? 'inner-tab-pill active' : 'inner-tab-pill'}
                onClick={() => onModeloAbertoTabSelect(tab.key)}
              >
                {tab.label}
              </button>
            ))}
          </div>

          <div className="inner-tab-panel">
            {modeloAbertoActiveTab === 'mapa' ? (
              !modeloAbertoLoadedTabs.mapa ? (
                <div className="empty-box">Carregando mapa do modelo...</div>
              ) : (
                <>
                <div className="row compact visualizacao-mapa-controls pesquisa-mapa-controls-row">
                  <label className="pesquisa-field pesquisa-mapa-modo-field">
                    Variável no mapa
                    <select
                      {...buildSelectAutofillProps('modeloAbertoMapaVar')}
                      value={modeloAbertoMapaVar}
                      onChange={(event) => void onModeloAbertoMapChange(event.target.value)}
                    >
                      {modeloAbertoMapaChoices.map((choice) => (
                        <option key={`modelo-aberto-mapa-${choice}`} value={choice}>{choice}</option>
                      ))}
                    </select>
                  </label>
                  <label className="pesquisa-field pesquisa-mapa-trabalhos-field">
                    Exibição dos trabalhos técnicos
                    <select
                      {...buildSelectAutofillProps('modeloAbertoTrabalhosTecnicosModelosModo')}
                      value={modeloAbertoTrabalhosTecnicosModelosModo === 'selecionados_e_anteriores'
                        ? MODELO_ABERTO_TRABALHOS_TECNICOS_PADRAO
                        : modeloAbertoTrabalhosTecnicosModelosModo}
                      onChange={(event) => void onModeloAbertoTrabalhosTecnicosModeChange(event.target.value)}
                    >
                      <option value="selecionados">Somente deste modelo</option>
                      <option value="selecionados_e_outras_versoes">Incluir demais versões do modelo</option>
                    </select>
                  </label>
                </div>
                <MapFrame html={modeloAbertoMapaHtml} payload={modeloAbertoMapaPayload} sessionId={sessionId} />
              </>
              )
            ) : null}

            {modeloAbertoActiveTab === 'trabalhos_tecnicos' ? (
              modeloAbertoLoadedTabs.trabalhos_tecnicos
                ? <ModeloTrabalhosTecnicosPanel trabalhos={modeloAbertoTrabalhosTecnicos} />
                : <div className="empty-box">Carregando trabalhos técnicos do modelo...</div>
            ) : null}

            {modeloAbertoActiveTab === 'dados_mercado'
              ? (modeloAbertoLoadedTabs.dados_mercado ? <DataTable table={modeloAbertoDados} maxHeight={620} /> : <div className="empty-box">Carregando dados de mercado...</div>)
              : null}
            {modeloAbertoActiveTab === 'metricas'
              ? (modeloAbertoLoadedTabs.metricas ? <DataTable table={modeloAbertoEstatisticas} maxHeight={620} /> : <div className="empty-box">Carregando métricas do modelo...</div>)
              : null}

            {modeloAbertoActiveTab === 'transformacoes' ? (
              modeloAbertoLoadedTabs.transformacoes ? (
                <>
                <div dangerouslySetInnerHTML={{ __html: modeloAbertoEscalasHtml }} />
                <h4 className="visualizacao-table-title">Dados com variáveis transformadas</h4>
                <DataTable table={modeloAbertoDadosTransformados} />
              </>
              ) : (
                <div className="empty-box">Carregando transformações do modelo...</div>
              )
            ) : null}

            {modeloAbertoActiveTab === 'resumo' ? (
              modeloAbertoLoadedTabs.resumo ? (
                <>
                <div className="equation-formats-section">
                  <h4>Equações do Modelo</h4>
                  <EquationFormatsPanel
                    equacoes={modeloAbertoEquacoes}
                    onDownload={(mode) => void onDownloadEquacaoModeloAberto(mode)}
                    disabled={modeloAbertoLoading}
                  />
                </div>
                <div dangerouslySetInnerHTML={{ __html: modeloAbertoResumoHtml }} />
              </>
              ) : (
                <div className="empty-box">Carregando resumo do modelo...</div>
              )
            ) : null}

            {modeloAbertoActiveTab === 'coeficientes'
              ? (modeloAbertoLoadedTabs.coeficientes ? <DataTable table={modeloAbertoCoeficientes} maxHeight={620} /> : <div className="empty-box">Carregando coeficientes do modelo...</div>)
              : null}
            {modeloAbertoActiveTab === 'obs_calc'
              ? (modeloAbertoLoadedTabs.obs_calc ? <DataTable table={modeloAbertoObsCalc} maxHeight={620} /> : <div className="empty-box">Carregando observados x calculados...</div>)
              : null}

            {modeloAbertoActiveTab === 'graficos' ? (
              modeloAbertoLoadedTabs.graficos ? (
                <>
                <div className="plot-grid-2-fixed">
                  <PlotFigure figure={modeloAbertoPlotObsCalc} title="Obs x Calc" />
                  <PlotFigure figure={modeloAbertoPlotResiduos} title="Resíduos" />
                  <PlotFigure figure={modeloAbertoPlotHistograma} title="Histograma" />
                  <PlotFigure figure={modeloAbertoPlotCook} title="Cook" forceHideLegend />
                </div>
                <div className="plot-full-width">
                  <PlotFigure figure={modeloAbertoPlotCorr} title="Correlação" className="plot-correlation-card" />
                </div>
              </>
              ) : (
                <div className="empty-box">Carregando gráficos do modelo...</div>
              )
            ) : null}
          </div>

          {modeloAbertoError ? <div className="error-line inline-error">{modeloAbertoError}</div> : null}
        </div>
        <LoadingOverlay
          show={modeloAbertoLoading || Boolean(modeloAbertoLoadingTabs[modeloAbertoActiveTab])}
          label={modeloAbertoLoading ? 'Carregando modelo...' : 'Carregando seção do modelo...'}
        />
      </div>
    )
  }

  return (
    <div className="tab-content">
      <SectionBlock
        step="1"
        title="Geolocalização do Avaliando"
        subtitle="Registre um endereço ou coordenadas do avaliando. O preenchimento desta seção não é obrigatório. Se você não informar localização, a pesquisa continua normal, a distância espacial dos modelos não será calculada e o avaliando não aparecerá no mapa gerado."
      >
        <div className="pesquisa-localizacao-section">
          {avaliandosGeolocalizados.length ? (
            <div className="pesquisa-localizacao-multi-grid">
              {avaliandosGeolocalizados.map((item, index) => (
                <LocalizacaoResumoCard
                  key={item.id}
                  title={`Avaliando ${index + 1}: Geolocalização registrada`}
                  localizacao={item}
                  className="pesquisa-localizacao-multi-card"
                  actions={(
                    <button
                      type="button"
                      className="pesquisa-localizacao-action pesquisa-localizacao-action-reset"
                      onClick={() => void onRemoverAvaliandoLocalizacao(item.id)}
                      disabled={localizacaoLoading || isPesquisaBusy}
                    >
                      Excluir avaliando
                    </button>
                  )}
                />
              ))}
            </div>
          ) : null}

          {localizacaoModo === 'coords' ? (
            <div className="pesquisa-localizacao-grid pesquisa-localizacao-grid-coords">
              <label className="pesquisa-field">
                Forma de localização
                <select
                  data-field="localizacaoModo"
                  {...buildSelectAutofillProps('localizacaoModo')}
                  value={localizacaoModo}
                  onChange={(event) => setLocalizacaoModo(event.target.value)}
                >
                  <option value="endereco">Endereço</option>
                  <option value="coords">Coordenadas</option>
                </select>
              </label>
              <label className="pesquisa-field">
                Latitude
                <NumberFieldInput field="latitude" value={localizacaoInputs.latitude} onChange={onLocalizacaoFieldChange} placeholder="-30.000000" />
              </label>
              <label className="pesquisa-field">
                Longitude
                <NumberFieldInput field="longitude" value={localizacaoInputs.longitude} onChange={onLocalizacaoFieldChange} placeholder="-51.000000" />
              </label>
              <div className="pesquisa-localizacao-actions-inline">
                <button
                  type="button"
                  className="pesquisa-localizacao-action pesquisa-localizacao-action-ok"
                  onClick={() => void onResolverLocalizacao()}
                  disabled={localizacaoLoading}
                >
                  {localizacaoLoading ? 'Adicionando...' : 'Adicionar'}
                </button>
                <button
                  type="button"
                  className="pesquisa-localizacao-action pesquisa-localizacao-action-reset"
                  onClick={onLimparFormularioLocalizacao}
                  disabled={localizacaoLoading}
                >
                  Limpar
                </button>
              </div>
            </div>
          ) : (
            <div className="pesquisa-localizacao-grid pesquisa-localizacao-grid-endereco">
              <label className="pesquisa-field">
                Forma de localização
                <select
                  data-field="localizacaoModo"
                  {...buildSelectAutofillProps('localizacaoModo')}
                  value={localizacaoModo}
                  onChange={(event) => setLocalizacaoModo(event.target.value)}
                >
                  <option value="endereco">Endereço</option>
                  <option value="coords">Coordenadas</option>
                </select>
              </label>
              <label className="pesquisa-field">
                CDLOG
                <NumberFieldInput field="cdlog" value={localizacaoInputs.cdlog} onChange={onLocalizacaoFieldChange} placeholder="Opcional" />
              </label>
              <label className="pesquisa-field pesquisa-localizacao-logradouro-field">
                Logradouro
                <SinglePillAutocomplete
                  value={localizacaoInputs.logradouro}
                  onChange={(nextValue) => atualizarCampoLocalizacao('logradouro', nextValue)}
                  options={logradouroOptions}
                  placeholder="Digite ou selecione um logradouro dos eixos"
                  panelTitle="Logradouros dos eixos"
                  emptyMessage="Nenhum logradouro encontrado nos eixos."
                  loading={logradouroOptionsLoading}
                  onOpenChange={(open) => {
                    if (open) void carregarSugestoesLogradouro()
                  }}
                  inputName={toInputName('logradouroEixosPesquisa')}
                  inputAutoComplete="new-password"
                />
              </label>
              <label className="pesquisa-field">
                Número
                <NumberFieldInput field="numero" value={localizacaoInputs.numero} onChange={onLocalizacaoFieldChange} placeholder="0" />
              </label>
              <div className="pesquisa-localizacao-actions-inline">
                <button
                  type="button"
                  className="pesquisa-localizacao-action pesquisa-localizacao-action-ok"
                  onClick={() => void onResolverLocalizacao()}
                  disabled={localizacaoLoading}
                >
                  {localizacaoLoading ? 'Adicionando...' : 'Adicionar'}
                </button>
                <button
                  type="button"
                  className="pesquisa-localizacao-action pesquisa-localizacao-action-reset"
                  onClick={onLimparFormularioLocalizacao}
                  disabled={localizacaoLoading}
                >
                  Limpar
                </button>
              </div>
            </div>
          )}

          {localizacaoStatus && !localizacaoAtiva ? <div className="status-line">{localizacaoStatus}</div> : null}
          {localizacaoError ? <div className="error-line inline-error">{localizacaoError}</div> : null}
        </div>
      </SectionBlock>

      <SectionBlock
        step="2"
        title="Filtros de Pesquisa"
        subtitle="Informe os dados do avaliando para filtrar os modelos. Todos os filtros são cumulativos."
        aside={(
          <button
            type="button"
            className={`pesquisa-admin-toggle${mostrarAdminConfig ? ' active' : ''}`}
            onClick={() => setMostrarAdminConfig((current) => !current)}
          >
            <span className="pesquisa-admin-toggle-icon" aria-hidden="true">⚙</span>
            <span>Configure as fontes dos campos</span>
          </button>
        )}
      >
        {mostrarAdminConfig ? (
          <PesquisaAdminConfigPanel onSaved={() => void onAdminConfigSalva()} />
        ) : null}

        <div className="pesquisa-fields-grid pesquisa-top-four-grid">
          <label className="pesquisa-field">
            Nome do modelo
            <ChipAutocompleteInput
              field="nomeModelo"
              value={filters.nomeModelo}
              onChange={onFieldChange}
              placeholder="Digite e pressione Enter"
              suggestions={sugestoes.nomes_modelo || []}
              panelTitle="Modelos sugeridos"
              loading={contextLoading && !sugestoesInicializadas}
            />
          </label>
          <label className="pesquisa-field">
            Tipo do modelo
            <select
              data-field="negociacaoModelo"
              {...buildSelectAutofillProps('negociacaoModelo')}
              value={filters.negociacaoModelo}
              onChange={onFieldChange}
            >
              <option value="">Indiferente</option>
              <option value="aluguel">Aluguel</option>
              <option value="venda">Venda</option>
            </select>
          </label>
          <label className="pesquisa-field">
            Finalidade genérica
            <select
              data-field="tipoModelo"
              {...buildSelectAutofillProps('tipoModelo')}
              value={filters.tipoModelo}
              onChange={onFieldChange}
            >
              <option value="">Todos</option>
              {opcoesTipoModelo.map((tipo) => (
                <option key={`tipo-modelo-${tipo}`} value={tipo}>{tipo}</option>
              ))}
            </select>
          </label>
          <label className="pesquisa-field">
            Finalidades cadastrais que devem estar contidas no modelo
            <ChipAutocompleteInput
              field="avalFinalidade"
              value={filters.avalFinalidade}
              onChange={onFieldChange}
              placeholder="Digite e pressione Enter"
              suggestions={sugestoes.finalidades || []}
              panelTitle="Finalidades sugeridas"
              loading={contextLoading && !sugestoesInicializadas}
            />
          </label>
        </div>

        <div className="pesquisa-avaliando-grid-v2">
          <div className="pesquisa-area-rh-grid">
            <label className="pesquisa-field">
              Área do imóvel
              <NumberFieldInput field="avalArea" value={filters.avalArea} onChange={onFieldChange} placeholder="0" />
            </label>
            <label className="pesquisa-field">
              RH do imóvel
              <NumberFieldInput field="avalRh" value={filters.avalRh} onChange={onFieldChange} placeholder="0" />
            </label>
          </div>

          <div className="pesquisa-bairro-zona-grid">
            <label className="pesquisa-field">
              Zonas de avaliação
              <ChipAutocompleteInput
                field="avalZona"
                value={filters.avalZona}
                onChange={onFieldChange}
                placeholder="Selecione uma ou mais zonas"
                suggestions={sugestoes.zonas_avaliacao || []}
                panelTitle="Zonas sugeridas"
                loading={contextLoading && !sugestoesInicializadas}
              />
            </label>
            <label className="pesquisa-field pesquisa-bairro-bottom-field">
              Bairros
              <ChipAutocompleteInput
                field="avalBairro"
                value={filters.avalBairro}
                onChange={onFieldChange}
                placeholder="Digite e pressione Enter"
                suggestions={sugestoes.bairros || []}
                panelTitle="Bairros sugeridos"
                loading={contextLoading && !sugestoesInicializadas}
              />
            </label>
          </div>
        </div>

        <div className="pesquisa-periodo-versoes-grid">
          <div className="pesquisa-periodo-fields">
            <label className="pesquisa-field">
              Data inicial
              <DateFieldInput field="dataMin" value={filters.dataMin} onChange={onFieldChange} />
            </label>
            <label className="pesquisa-field">
              Data final
              <DateFieldInput field="dataMax" value={filters.dataMax} onChange={onFieldChange} />
            </label>
          </div>

          <label className="pesquisa-field pesquisa-versionamento-field">
            Versionamento dos modelos
            <select
              data-field="versionamentoModelos"
              {...buildSelectAutofillProps('versionamentoModelos')}
              value={filters.versionamentoModelos}
              onChange={onFieldChange}
            >
              <option value="incluir_antigos">Exibir todos os modelos</option>
              <option value="atuais">Exibir somente versões mais atuais</option>
            </select>
          </label>
        </div>

        <div className="row pesquisa-actions pesquisa-actions-primary">
          <button
            type="button"
            className={searchLoading ? 'is-loading' : ''}
            onClick={() => void buscarModelos()}
            disabled={isPesquisaBusy}
          >
            {searchLoading ? (
              <>
                <span className="repo-open-btn-spinner" aria-hidden="true" />
                <span>Pesquisando...</span>
              </>
            ) : 'Pesquisar'}
          </button>
          <button type="button" onClick={() => void onLimparFiltros()} disabled={isPesquisaBusy}>
            Limpar filtros
          </button>
        </div>

        {error ? <div className="error-line inline-error">{error}</div> : null}
      </SectionBlock>

      <div ref={sectionResultadosRef}>
        <SectionBlock
          step="3"
          title="Resultados"
          subtitle="Modelos aceitos para os parametros do avaliando informado."
        >
        <div className="pesquisa-results-toolbar">
          <div className="pesquisa-summary-line">
            <strong>{formatCount(result.total_filtrado)}</strong>{' '}
            modelo(s) aceito(s) de <strong>{formatCount(result.total_geral)}</strong>.
          </div>
          {localizacaoMultipla ? (
            <label className="pesquisa-results-criterio">
              Critério espacial
              <select
                {...buildSelectAutofillProps('criterioEspacial')}
                value={criterioEspacial}
                onChange={(event) => setCriterioEspacial(event.target.value)}
              >
                {CRITERIO_ESPACIAL_OPTIONS.map((option) => (
                  <option key={`criterio-espacial-${option.value}`} value={option.value}>{option.label}</option>
                ))}
              </select>
            </label>
          ) : null}
          <div className="pesquisa-results-toolbar-actions">
            <ShareLinkButton
              href={pesquisaShareHref}
              label="Copiar link da pesquisa"
              disabled={pesquisaShareDisabled}
              title={pesquisaShareDisabled ? 'O compartilhamento da pesquisa suporta apenas um avaliando na versão atual.' : pesquisaShareHref}
            />
            {resultIds.length ? (
              <label className="pesquisa-select-all">
                <input ref={selectAllRef} type="checkbox" checked={todosSelecionados} onChange={onToggleSelecionarTodos} />
                Selecionar todos os exibidos
              </label>
            ) : null}
          </div>
        </div>

        {!modelosOrdenados.length ? (
          <div className="empty-box">
            {!pesquisaInicializada
              ? 'Defina os filtros desejados e clique em Pesquisar.'
              : 'Nenhum modelo aceitou os parametros do avaliando informado.'}
          </div>
        ) : (
          <div className="pesquisa-card-grid">
            {modelosOrdenados.map((modelo) => {
              const selecionado = selectedIds.includes(modelo.id)
              const faixaDataRecency = getFaixaDataRecencyInfo(modelo.faixa_data)
              const finalidadesText = uppercaseListText(modelo.finalidades || [])
              const bairrosText = uppercaseListText(modelo.bairros || [])
              const variaveisText = buildVariablesDisplay(modelo)
              const observacaoText = String(modelo.observacao_modelo || '').trim()
              const resumoEspacial = modelo?.distancia_resumo || null
              const coberturaEspacial = formatResumoEspacialCobertura(resumoEspacial)
              const cardClassName = [
                'pesquisa-card',
                selecionado ? 'is-selected' : '',
              ].filter(Boolean).join(' ')

              return (
                <article key={modelo.id} className={cardClassName}>
                  <div className="pesquisa-card-top">
                    <h4 className="pesquisa-card-title">{modelo.nome_modelo || modelo.arquivo}</h4>
                    <div className="pesquisa-card-divider" aria-hidden="true" />
                    <div className="pesquisa-card-actions">
                      <button
                        type="button"
                        className={`btn-pesquisa-map-toggle${selecionado ? ' is-selected' : ''}`}
                        onClick={() => onToggleSelecionado(modelo.id)}
                      >
                        {selecionado ? 'Desmarcar' : 'Selecionar'}
                      </button>
                      <button type="button" className="btn-pesquisa-open" onClick={() => void onAbrirModelo(modelo)}>
                        Abrir
                      </button>
                      <button type="button" className="btn-pesquisa-eval" onClick={() => onUsarEmAvaliacao(modelo)}>
                        Avaliação
                      </button>
                    </div>
                    <div className="pesquisa-card-body">
                      <div className="pesquisa-card-dados-list">
                        {localizacaoMultipla ? (
                          <>
                            <div><strong>Resumo espacial:</strong> {formatResumoEspacial(resumoEspacial)}</div>
                            <div><strong>Distâncias por avaliando:</strong> {formatDistanciasPorAvaliando(modelo?.distancias_avaliandos || [])}</div>
                            {coberturaEspacial ? <div><strong>Cobertura espacial:</strong> {coberturaEspacial}</div> : null}
                          </>
                        ) : (
                          <div><strong>Distância:</strong> {String(modelo.distancia_label || '').trim() || formatDistanceKm(modelo.distancia_km)}</div>
                        )}
                        <div><strong>Tipo:</strong> {formatTipoImovel(modelo)}</div>
                        <div><strong>Autor:</strong> {modelo.autor || '-'}</div>
                        <div><strong>Dados:</strong> {formatCount(modelo.total_dados)}</div>
                        <div><strong>Avaliandos:</strong> {formatCount(modelo.total_trabalhos)}</div>
                        <div><strong>Faixa area:</strong> {formatRange(modelo.faixa_area)}</div>
                        <div><strong>Faixa RH:</strong> {formatRange(modelo.faixa_rh)}</div>
                        <div>
                          <strong>Faixa data:</strong> {formatRange(modelo.faixa_data)}
                          {faixaDataRecency.label ? (
                            <span className={`pesquisa-card-faixa-data-badge is-aged-${faixaDataRecency.tone}`}>
                              {faixaDataRecency.label}
                            </span>
                          ) : null}
                        </div>
                      </div>
                    </div>
                    <div className="pesquisa-card-meta-actions">
                      <CompactHoverList
                        label="Finalidades"
                        buttonLabel="Finalidades"
                        previewText={finalidadesText}
                        modalText={finalidadesText}
                      />
                      <CompactHoverList
                        label="Bairros"
                        buttonLabel="Bairros"
                        previewText={bairrosText}
                        modalText={bairrosText}
                      />
                      <CompactHoverList
                        label="Variáveis"
                        buttonLabel="Variáveis"
                        previewText={variaveisText}
                        modalText={variaveisText}
                        previewContent={buildVariablesContent(variaveisText)}
                        modalContent={buildVariablesContent(variaveisText)}
                      />
                      <CompactHoverList
                        label="Observação"
                        buttonLabel="Obs"
                        previewText={observacaoText}
                        modalText={observacaoText}
                      />
                    </div>
                  </div>

                  {modelo.status !== 'ok' ? <div className="inline-error pesquisa-card-error">{modelo.erro_leitura || 'Falha ao ler modelo.'}</div> : null}
                </article>
              )
            })}
          </div>
        )}
        </SectionBlock>
      </div>

      <div ref={sectionMapaRef}>
        <SectionBlock
          step="4"
          title="Mapa"
          subtitle={localizacaoAtiva
            ? (localizacaoMultipla
              ? 'Plote os modelos selecionados com dados de mercado ou cobertura dos modelos, com os avaliandos destacados.'
              : 'Plote os modelos selecionados com dados de mercado ou cobertura dos modelos, com o avaliando destacado.')
            : 'Plote os modelos selecionados com dados de mercado ou cobertura dos modelos.'}
        >
          <div className="pesquisa-summary-line">
            <strong>{formatCount(selectedIds.length)}</strong> modelo(s) selecionado(s) para plotagem.
          </div>
          <div className="pesquisa-summary-line">
            <strong>{localizacaoMultipla ? 'Avaliandos geolocalizados:' : 'Localização do avaliando:'}</strong>{' '}
            {localizacaoAtiva ? (localizacaoMultipla ? formatCount(avaliandosGeoPayload.length) : 'ativa') : 'não definida'}
          </div>

          <div className="row pesquisa-actions pesquisa-mapa-actions">
            <button type="button" onClick={() => void onGerarMapaSelecionados()} disabled={mapaLoading || !selectedIds.length}>
              {mapaLoading ? 'Gerando mapa...' : 'Plotar mapa dos selecionados'}
            </button>
          </div>

          {mapaError ? <div className="error-line inline-error">{mapaError}</div> : null}

          {mapaHtmlAtual ? (
            <div className="row pesquisa-actions pesquisa-mapa-actions pesquisa-mapa-controls-row">
              <label className="pesquisa-field pesquisa-mapa-modo-field">
                Exibição do mapa
                <select
                  {...buildSelectAutofillProps('mapaModoExibicao')}
                  value={mapaModoExibicao}
                  onChange={onMapaModoExibicaoChange}
                >
                  <option value="pontos">Pontos representando dados de mercado</option>
                  <option value="cobertura">Cobertura dos modelos</option>
                </select>
              </label>

              <label className="pesquisa-field pesquisa-mapa-trabalhos-field">
                Exibição dos trabalhos técnicos
                <select
                  {...buildSelectAutofillProps('mapaTrabalhosTecnicosModelosModo')}
                  value={mapaTrabalhosTecnicosModelosModo === 'selecionados_e_anteriores'
                    ? 'selecionados_e_outras_versoes'
                    : mapaTrabalhosTecnicosModelosModo}
                  onChange={(event) => setMapaTrabalhosTecnicosModelosModo(event.target.value)}
                  disabled={mapaLoading || !selectedIds.length}
                >
                  <option value="selecionados">Somente dos modelos selecionados</option>
                  <option value="selecionados_e_outras_versoes">Incluir demais versões dos modelos</option>
                </select>
              </label>

              {localizacaoAtiva ? (
                <label className="pesquisa-field pesquisa-mapa-proximidade-field">
                  Trabalhos técnicos adicionais por raio
                  <select
                    {...buildSelectAutofillProps('mapaTrabalhosTecnicosProximidadeModo')}
                    value={mapaTrabalhosTecnicosProximidadeModo}
                    onChange={(event) => setMapaTrabalhosTecnicosProximidadeModo(event.target.value)}
                    disabled={mapaLoading || !selectedIds.length}
                  >
                  <option value="sem_proximidade">Não mostrar</option>
                  <option value="proximos_ao_avaliando">
                    {localizacaoMultipla ? 'Mostrar próximos de cada avaliando' : 'Mostrar próximos do avaliando'}
                  </option>
                </select>
              </label>
              ) : null}

              {localizacaoAtiva && mapaTrabalhosTecnicosProximidadeModo === 'proximos_ao_avaliando' ? (
                <label className="pesquisa-field pesquisa-mapa-raio-field">
                  {localizacaoMultipla ? 'Raio de cada avaliando (m)' : 'Raio do avaliando (m)'}
                  <div className="pesquisa-mapa-raio-control">
                    <input
                      type="range"
                      min="0"
                      max="5000"
                      step="100"
                      value={mapaTrabalhosTecnicosRaio}
                      onChange={(event) => setMapaTrabalhosTecnicosRaio(Number(event.target.value))}
                      disabled={mapaLoading || !selectedIds.length}
                    />
                    <span className="pesquisa-mapa-raio-value">{formatCount(mapaTrabalhosTecnicosRaio)} m</span>
                  </div>
                </label>
              ) : null}
            </div>
          ) : null}

          {(mapaHtmlAtual || mapaPayloadAtual)
            ? <MapFrame html={mapaHtmlAtual} payload={mapaPayloadAtual} sessionId={sessionId} />
            : <div className="empty-box">Nenhum mapa gerado ainda.</div>}
        </SectionBlock>
      </div>

      <LoadingOverlay show={searchLoading} label="Pesquisando modelos..." />
      <LoadingOverlay show={modeloAbertoLoading} label="Carregando modelo..." />
    </div>
  )
}
