import React, { useEffect, useMemo, useRef, useState } from 'react'
import { api, downloadBlob } from '../api'
import DataTable from './DataTable'
import EquationFormatsPanel from './EquationFormatsPanel'
import LoadingOverlay from './LoadingOverlay'
import MapFrame from './MapFrame'
import PlotFigure from './PlotFigure'
import SectionBlock from './SectionBlock'
import SinglePillAutocomplete from './SinglePillAutocomplete'

const INNER_TABS = [
  { key: 'mapa', label: 'Mapa' },
  { 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' },
  { key: 'avaliacao', label: 'Avaliação' },
  { key: 'avaliacao_massa', label: 'Avaliação em Massa' },
]
const BASE_COMPARACAO_SEM_BASE = '__none__'

export default function VisualizacaoTab({ sessionId }) {
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')
  const [status, setStatus] = useState('')
  const [badgeHtml, setBadgeHtml] = useState('')

  const [uploadedFile, setUploadedFile] = useState(null)
  const [uploadDragOver, setUploadDragOver] = useState(false)
  const [modeloLoadSource, setModeloLoadSource] = useState('')
  const [repoModelos, setRepoModelos] = useState([])
  const [repoModeloSelecionado, setRepoModeloSelecionado] = useState('')
  const [repoModelosLoading, setRepoModelosLoading] = useState(false)
  const [repoFonteModelos, setRepoFonteModelos] = useState('')

  const [dados, setDados] = useState(null)
  const [estatisticas, setEstatisticas] = useState(null)
  const [escalasHtml, setEscalasHtml] = useState('')
  const [dadosTransformados, setDadosTransformados] = useState(null)
  const [resumoHtml, setResumoHtml] = useState('')
  const [equacoes, setEquacoes] = useState(null)
  const [coeficientes, setCoeficientes] = useState(null)
  const [obsCalc, setObsCalc] = useState(null)

  const [plotObsCalc, setPlotObsCalc] = useState(null)
  const [plotResiduos, setPlotResiduos] = useState(null)
  const [plotHistograma, setPlotHistograma] = useState(null)
  const [plotCook, setPlotCook] = useState(null)
  const [plotCorr, setPlotCorr] = useState(null)

  const [mapaHtml, setMapaHtml] = useState('')
  const [mapaChoices, setMapaChoices] = useState(['Visualização Padrão'])
  const [mapaVar, setMapaVar] = useState('Visualização Padrão')

  const [camposAvaliacao, setCamposAvaliacao] = useState([])
  const valoresAvaliacaoRef = useRef({})
  const [avaliacaoFormVersion, setAvaliacaoFormVersion] = useState(0)
  const [confirmarLimpezaAvaliacoes, setConfirmarLimpezaAvaliacoes] = useState(false)
  const [resultadoAvaliacaoHtml, setResultadoAvaliacaoHtml] = useState('')
  const [baseChoices, setBaseChoices] = useState([])
  const [baseValue, setBaseValue] = useState('')

  const [activeInnerTab, setActiveInnerTab] = useState('mapa')
  const deleteConfirmTimersRef = useRef({})
  const uploadInputRef = useRef(null)
  const temAvaliacoes = Array.isArray(baseChoices) && baseChoices.length > 0
  const repoModeloOptions = useMemo(
    () => (repoModelos || []).map((item) => ({
      value: String(item?.id || ''),
      label: String(item?.nome_modelo || item?.arquivo || item?.id || ''),
      secondary: String(item?.arquivo || ''),
    })).filter((item) => item.value && item.label),
    [repoModelos],
  )

  function resetConteudoVisualizacao() {
    setDados(null)
    setEstatisticas(null)
    setEscalasHtml('')
    setDadosTransformados(null)
    setResumoHtml('')
    setEquacoes(null)
    setCoeficientes(null)
    setObsCalc(null)

    setPlotObsCalc(null)
    setPlotResiduos(null)
    setPlotHistograma(null)
    setPlotCook(null)
    setPlotCorr(null)

    setMapaHtml('')
    setMapaChoices(['Visualização Padrão'])
    setMapaVar('Visualização Padrão')

    setCamposAvaliacao([])
    valoresAvaliacaoRef.current = {}
    setAvaliacaoFormVersion((prev) => prev + 1)
    setConfirmarLimpezaAvaliacoes(false)
    setResultadoAvaliacaoHtml('')
    setBaseChoices([])
    setBaseValue('')

    setActiveInnerTab('mapa')
  }

  function applyExibicaoResponse(resp) {
    setDados(resp.dados || null)
    setEstatisticas(resp.estatisticas || null)
    setEscalasHtml(resp.escalas_html || '')
    setDadosTransformados(resp.dados_transformados || null)
    setResumoHtml(resp.resumo_html || '')
    setEquacoes(resp.equacoes || null)
    setCoeficientes(resp.coeficientes || null)
    setObsCalc(resp.obs_calc || null)

    setPlotObsCalc(resp.grafico_obs_calc || null)
    setPlotResiduos(resp.grafico_residuos || null)
    setPlotHistograma(resp.grafico_histograma || null)
    setPlotCook(resp.grafico_cook || null)
    setPlotCorr(resp.grafico_correlacao || null)

    setMapaHtml(resp.mapa_html || '')
    setMapaChoices(resp.mapa_choices || ['Visualização Padrão'])
    setMapaVar('Visualização Padrão')

    setCamposAvaliacao(resp.campos_avaliacao || [])
    const values = {}
    ;(resp.campos_avaliacao || []).forEach((campo) => {
      values[campo.coluna] = ''
    })
    valoresAvaliacaoRef.current = values
    setAvaliacaoFormVersion((prev) => prev + 1)
    setConfirmarLimpezaAvaliacoes(false)
    setResultadoAvaliacaoHtml('')
    setBaseChoices([])
    setBaseValue('')
  }

  async function withBusy(fn) {
    setLoading(true)
    setError('')
    try {
      await fn()
    } catch (err) {
      setError(err.message)
    } finally {
      setLoading(false)
    }
  }

  function formatarFonteRepositorio(fonte) {
    if (!fonte || typeof fonte !== 'object') return ''
    const provider = String(fonte.provider || '').toLowerCase()
    if (provider === 'hf_dataset') {
      const repo = String(fonte.repo_id || '').trim()
      const revision = String(fonte.revision || '').trim()
      const degradado = Boolean(fonte.degraded)
      const sufixo = degradado ? ' (modo contingência)' : ''
      return `Fonte: HF Dataset${repo ? ` (${repo})` : ''}${revision ? ` | revisão ${revision.slice(0, 8)}` : ''}${sufixo}`
    }
    return 'Fonte: pasta local'
  }

  function aplicarRespostaModelosRepositorio(resp) {
    const modelos = Array.isArray(resp?.modelos) ? resp.modelos : []
    setRepoModelos(modelos)
    setRepoFonteModelos(formatarFonteRepositorio(resp?.fonte || null))
    setRepoModeloSelecionado((prev) => {
      const atual = String(prev || '')
      if (atual && modelos.some((item) => String(item.id) === atual)) return atual
      return ''
    })
  }

  async function carregarModelosRepositorio() {
    setRepoModelosLoading(true)
    try {
      const resp = await api.visualizacaoRepositorioModelos()
      aplicarRespostaModelosRepositorio(resp)
    } catch (err) {
      setError(err.message || 'Falha ao carregar modelos do repositório.')
      setRepoModelos([])
      setRepoModeloSelecionado('')
      setRepoFonteModelos('')
    } finally {
      setRepoModelosLoading(false)
    }
  }

  useEffect(() => {
    let ativo = true
    if (!sessionId) return () => {
      ativo = false
    }

    setRepoModelosLoading(true)
    api.visualizacaoRepositorioModelos()
      .then((resp) => {
        if (!ativo) return
        aplicarRespostaModelosRepositorio(resp)
      })
      .catch(() => {
        if (!ativo) return
        setRepoModelos([])
        setRepoModeloSelecionado('')
        setRepoFonteModelos('')
      })
      .finally(() => {
        if (!ativo) return
        setRepoModelosLoading(false)
      })

    return () => {
      ativo = false
    }
  }, [sessionId])

  async function onUploadModel(arquivo = null) {
    const arquivoUpload = arquivo || uploadedFile
    if (!sessionId || !arquivoUpload) return
    setModeloLoadSource('upload')
    await withBusy(async () => {
      resetConteudoVisualizacao()
      const uploadResp = await api.uploadVisualizacaoFile(sessionId, arquivoUpload)
      setStatus(uploadResp.status || '')
      setBadgeHtml(uploadResp.badge_html || '')

      const exibirResp = await api.exibirVisualizacao(sessionId)
      applyExibicaoResponse(exibirResp)
    })
  }

  async function onCarregarModeloRepositorio() {
    if (!sessionId || !repoModeloSelecionado) return
    setModeloLoadSource('repo')
    await withBusy(async () => {
      resetConteudoVisualizacao()
      const uploadResp = await api.visualizacaoRepositorioCarregar(sessionId, repoModeloSelecionado)
      setStatus(uploadResp.status || '')
      setBadgeHtml(uploadResp.badge_html || '')

      const exibirResp = await api.exibirVisualizacao(sessionId)
      applyExibicaoResponse(exibirResp)
      setUploadedFile(null)
    })
  }

  function onUploadInputChange(event) {
    const input = event.target
    const file = input.files?.[0] ?? null
    setModeloLoadSource('upload')
    setUploadedFile(file)
    input.value = ''
    if (!file || loading) return
    void onUploadModel(file)
  }

  function onUploadDropZoneDragOver(event) {
    event.preventDefault()
    event.dataTransfer.dropEffect = 'copy'
    setUploadDragOver(true)
  }

  function onUploadDropZoneDragLeave(event) {
    event.preventDefault()
    if (!event.currentTarget.contains(event.relatedTarget)) {
      setUploadDragOver(false)
    }
  }

  function onUploadDropZoneDrop(event) {
    event.preventDefault()
    setUploadDragOver(false)
    const file = event.dataTransfer?.files?.[0]
    if (!file || loading) return
    setModeloLoadSource('upload')
    setUploadedFile(file)
    void onUploadModel(file)
  }

  async function onMapChange(value) {
    setMapaVar(value)
    if (!sessionId) return
    await withBusy(async () => {
      const resp = await api.updateVisualizacaoMap(sessionId, value)
      setMapaHtml(resp.mapa_html || '')
    })
  }

  async function onCalcularAvaliacao() {
    if (!sessionId) return
    await withBusy(async () => {
      const resp = await api.evaluationCalculateViz(sessionId, valoresAvaliacaoRef.current, baseValue || null)
      setResultadoAvaliacaoHtml(resp.resultado_html || '')
      setBaseChoices(resp.base_choices || [])
      setBaseValue(resp.base_value || '')
      setConfirmarLimpezaAvaliacoes(false)
    })
  }

  function onResetCamposAvaliacao() {
    const limpo = {}
    camposAvaliacao.forEach((campo) => {
      limpo[campo.coluna] = ''
    })
    valoresAvaliacaoRef.current = limpo
    setAvaliacaoFormVersion((prev) => prev + 1)
  }

  async function onClearAvaliacao() {
    if (!sessionId) return
    await withBusy(async () => {
      const resp = await api.evaluationClearViz(sessionId)
      setResultadoAvaliacaoHtml(resp.resultado_html || '')
      setBaseChoices(resp.base_choices || [])
      setBaseValue(resp.base_value || '')
      setConfirmarLimpezaAvaliacoes(false)
    })
  }

  async function onDeleteAvaliacao(indice) {
    if (!sessionId) return
    await withBusy(async () => {
      const resp = await api.evaluationDeleteViz(sessionId, indice ? String(indice) : null, baseValue || null)
      setResultadoAvaliacaoHtml(resp.resultado_html || '')
      setBaseChoices(resp.base_choices || [])
      setBaseValue(resp.base_value || '')
      setConfirmarLimpezaAvaliacoes(false)
    })
  }

  function onAvaliacaoResultadoClick(event) {
    const ativarExclusao = event.target.closest('[data-avaliacao-delete-arm]')
    if (ativarExclusao) {
      const indice = ativarExclusao.getAttribute('data-avaliacao-delete-index')
      if (!indice) return

      const cell = ativarExclusao.closest('td')
      const botaoConfirmar = cell?.querySelector(`[data-avaliacao-delete-confirm="${indice}"]`)
      if (!botaoConfirmar) return

      ativarExclusao.style.display = 'none'
      botaoConfirmar.style.display = 'inline-block'

      const timerKey = String(indice)
      if (deleteConfirmTimersRef.current[timerKey]) {
        clearTimeout(deleteConfirmTimersRef.current[timerKey])
      }
      deleteConfirmTimersRef.current[timerKey] = window.setTimeout(() => {
        botaoConfirmar.style.display = 'none'
        ativarExclusao.style.display = 'inline'
        delete deleteConfirmTimersRef.current[timerKey]
      }, 10000)
      return
    }

    const confirmarExclusao = event.target.closest('[data-avaliacao-delete-confirm]')
    if (!confirmarExclusao) return
    const indice = confirmarExclusao.getAttribute('data-avaliacao-delete-confirm')
    if (!indice) return

    const timerKey = String(indice)
    if (deleteConfirmTimersRef.current[timerKey]) {
      clearTimeout(deleteConfirmTimersRef.current[timerKey])
      delete deleteConfirmTimersRef.current[timerKey]
    }
    onDeleteAvaliacao(indice)
  }

  async function onBaseChange(value) {
    setBaseValue(value)
    if (!sessionId) return
    await withBusy(async () => {
      const resp = await api.evaluationBaseViz(sessionId, value)
      setResultadoAvaliacaoHtml(resp.resultado_html || '')
    })
  }

  async function onExportAvaliacoes() {
    if (!sessionId) return
    await withBusy(async () => {
      const blob = await api.exportEvaluationViz(sessionId)
      downloadBlob(blob, 'avaliacoes_visualizacao.xlsx')
    })
  }

  async function onDownloadEquacao(mode) {
    if (!sessionId || !mode) return
    await withBusy(async () => {
      const blob = await api.exportEquationViz(sessionId, mode)
      const sufixo = String(mode) === 'excel_sab' ? 'estilo_sab' : 'excel'
      downloadBlob(blob, `equacao_modelo_${sufixo}.xlsx`)
    })
  }

  return (
    <div className="tab-content">
      <SectionBlock step="1" title="Carregar Modelo .dai" subtitle="Carregue o arquivo e o conteúdo será exibido automaticamente.">
        {!modeloLoadSource ? (
          <div className="model-source-choice-grid">
            <button
              type="button"
              className="model-source-choice-btn model-source-choice-btn-primary"
              onClick={() => setModeloLoadSource('repo')}
              disabled={loading}
            >
              Carregar modelo do repositório
            </button>
            <button
              type="button"
              className="model-source-choice-btn model-source-choice-btn-secondary"
              onClick={() => setModeloLoadSource('upload')}
              disabled={loading}
            >
              Fazer upload de modelo
            </button>
          </div>
        ) : (
          <div className="model-source-flow">
            <div className="model-source-flow-head">
              <button
                type="button"
                className="model-source-back-btn"
                onClick={() => setModeloLoadSource('')}
                disabled={loading}
              >
                Voltar
              </button>
            </div>

            {modeloLoadSource === 'repo' ? (
              <div className="row upload-repo-row">
                <label className="upload-repo-field">
                  Modelo do repositório
                  <SinglePillAutocomplete
                    value={repoModeloSelecionado}
                    onChange={setRepoModeloSelecionado}
                    options={repoModeloOptions}
                    placeholder={repoModelosLoading ? 'Carregando lista...' : repoModeloOptions.length > 0 ? 'Digite para buscar modelo' : 'Nenhum modelo disponível'}
                    emptyMessage={repoModeloOptions.length > 0 ? 'Nenhum modelo encontrado.' : 'Nenhum modelo disponível.'}
                    loading={repoModelosLoading}
                    disabled={loading || repoModelosLoading || repoModeloOptions.length === 0}
                  />
                </label>
                <div className="row compact upload-repo-actions">
                  <button type="button" onClick={onCarregarModeloRepositorio} disabled={loading || repoModelosLoading || !repoModeloSelecionado}>
                    Carregar do repositório
                  </button>
                  <button type="button" onClick={() => void carregarModelosRepositorio()} disabled={loading || repoModelosLoading}>
                    Atualizar lista
                  </button>
                </div>
                {repoFonteModelos ? <div className="section1-empty-hint">{repoFonteModelos}</div> : null}
              </div>
            ) : null}

            {modeloLoadSource === 'upload' ? (
              <div
                className={`upload-dropzone${uploadDragOver ? ' is-dragover' : ''}`}
                onDragOver={onUploadDropZoneDragOver}
                onDragEnter={onUploadDropZoneDragOver}
                onDragLeave={onUploadDropZoneDragLeave}
                onDrop={onUploadDropZoneDrop}
              >
                <input
                  ref={uploadInputRef}
                  type="file"
                  className="upload-hidden-input"
                  accept=".dai"
                  onChange={onUploadInputChange}
                />
                <div className="row upload-dropzone-main">
                  <button
                    type="button"
                    className="btn-upload-select"
                    onClick={() => uploadInputRef.current?.click()}
                    disabled={loading}
                  >
                    Selecionar arquivo
                  </button>
                </div>
                <div className="upload-dropzone-hint">Ou arraste e solte aqui para carregar automaticamente.</div>
              </div>
            ) : null}
          </div>
        )}
        {status ? <div className="status-line">{status}</div> : null}
        {badgeHtml ? <div className="upload-badge-block" dangerouslySetInnerHTML={{ __html: badgeHtml }} /> : null}
      </SectionBlock>

      {dados ? (
        <SectionBlock step="2" title="Conteúdo do Modelo" subtitle="Carregue o modelo no topo e navegue pelas abas internas abaixo.">
          <div className="inner-tabs" role="tablist" aria-label="Abas internas de visualização">
            {INNER_TABS.map((tab) => (
              <button
                key={tab.key}
                type="button"
                className={activeInnerTab === tab.key ? 'inner-tab-pill active' : 'inner-tab-pill'}
                onClick={() => setActiveInnerTab(tab.key)}
              >
                {tab.label}
              </button>
            ))}
          </div>

          <div className="inner-tab-panel">
            {activeInnerTab === 'mapa' ? (
              <>
                <div className="row compact visualizacao-mapa-controls">
                  <label>Variável no mapa</label>
                  <select value={mapaVar} onChange={(e) => onMapChange(e.target.value)}>
                    {mapaChoices.map((choice) => (
                      <option key={choice} value={choice}>{choice}</option>
                    ))}
                  </select>
                </div>
                <MapFrame html={mapaHtml} />
              </>
            ) : null}

            {activeInnerTab === 'dados_mercado' ? (
              <DataTable table={dados} maxHeight={620} />
            ) : null}

            {activeInnerTab === 'metricas' ? (
              <DataTable table={estatisticas} maxHeight={620} />
            ) : null}

            {activeInnerTab === 'transformacoes' ? (
              <>
                <div dangerouslySetInnerHTML={{ __html: escalasHtml }} />
                <h4 className="visualizacao-table-title">Dados com variáveis transformadas</h4>
                <DataTable table={dadosTransformados} />
              </>
            ) : null}

            {activeInnerTab === 'resumo' ? (
              <>
                <div className="equation-formats-section">
                  <h4>Equações do Modelo</h4>
                  <EquationFormatsPanel
                    equacoes={equacoes}
                    onDownload={(mode) => void onDownloadEquacao(mode)}
                    disabled={loading}
                  />
                </div>
                <div dangerouslySetInnerHTML={{ __html: resumoHtml }} />
              </>
            ) : null}

            {activeInnerTab === 'coeficientes' ? (
              <DataTable table={coeficientes} maxHeight={620} />
            ) : null}

            {activeInnerTab === 'obs_calc' ? (
              <DataTable table={obsCalc} maxHeight={620} />
            ) : null}

            {activeInnerTab === 'graficos' ? (
              <>
                <div className="plot-grid-2-fixed">
                  <PlotFigure figure={plotObsCalc} title="Obs x Calc" />
                  <PlotFigure figure={plotResiduos} title="Resíduos" />
                  <PlotFigure figure={plotHistograma} title="Histograma" />
                  <PlotFigure figure={plotCook} title="Cook" forceHideLegend />
                </div>
                <div className="plot-full-width">
                  <PlotFigure figure={plotCorr} title="Correlação" className="plot-correlation-card" />
                </div>
              </>
            ) : null}

            {activeInnerTab === 'avaliacao' ? (
              <>
                <div className="equation-formats-section avaliacao-equacao-section">
                  <h5>Equação (estilo SAB)</h5>
                  <div className="equation-box equation-box-plain">
                    {equacoes?.excel_sab || 'Equação indisponível.'}
                  </div>
                </div>
                <div className="avaliacao-groups">
                  <div className="subpanel avaliacao-group">
                    <h4>Parâmetros</h4>
                    <div className="avaliacao-grid" key={`avaliacao-grid-viz-${avaliacaoFormVersion}`}>
                      {camposAvaliacao.map((campo) => (
                        <div key={`campo-${campo.coluna}`} className="avaliacao-card">
                          <label>{String(campo?.rotulo || campo?.coluna || '')}</label>
                          {campo.tipo === 'dicotomica' ? (
                            <select
                              defaultValue={String(valoresAvaliacaoRef.current[campo.coluna] ?? '')}
                              onChange={(e) => {
                                valoresAvaliacaoRef.current[campo.coluna] = e.target.value
                              }}
                            >
                              <option value="">Selecione</option>
                              {(campo.opcoes || [0, 1]).map((opcao) => (
                                <option key={`op-viz-${campo.coluna}-${opcao}`} value={String(opcao)}>
                                  {opcao}
                                </option>
                              ))}
                            </select>
                          ) : (
                            <input
                              type="number"
                              defaultValue={valoresAvaliacaoRef.current[campo.coluna] ?? ''}
                              placeholder={campo.placeholder || ''}
                              onChange={(e) => {
                                valoresAvaliacaoRef.current[campo.coluna] = e.target.value
                              }}
                            />
                          )}
                        </div>
                      ))}
                    </div>
                    <div className="row-wrap avaliacao-actions-row">
                      <button onClick={onCalcularAvaliacao} disabled={loading}>Calcular</button>
                      <button onClick={onResetCamposAvaliacao} disabled={loading}>Resetar campos</button>
                    </div>
                  </div>

                  {temAvaliacoes ? (
                    <div className="subpanel avaliacao-group">
                      <h4>Avaliações</h4>
                      <div className="row avaliacao-base-row">
                        <label>Base comparação</label>
                        <select value={baseValue || ''} onChange={(e) => onBaseChange(e.target.value)}>
                          <option value={BASE_COMPARACAO_SEM_BASE}>Sem base</option>
                          {baseChoices.map((choice) => (
                            <option key={`base-${choice}`} value={choice}>{choice}</option>
                          ))}
                        </select>
                        <button type="button" className="btn-avaliacao-export" onClick={onExportAvaliacoes} disabled={loading}>
                          Exportar avaliações
                        </button>
                        {!confirmarLimpezaAvaliacoes ? (
                          <button
                            type="button"
                            className="btn-avaliacao-clear"
                            onClick={() => setConfirmarLimpezaAvaliacoes(true)}
                            disabled={loading}
                          >
                            Limpar avaliações
                          </button>
                        ) : (
                          <div className="avaliacao-clear-confirm avaliacao-clear-confirm-inline">
                            <span>Confirmar limpeza?</span>
                            <button type="button" className="btn-avaliacao-clear" onClick={onClearAvaliacao} disabled={loading}>
                              Confirmar
                            </button>
                            <button type="button" onClick={() => setConfirmarLimpezaAvaliacoes(false)} disabled={loading}>
                              Cancelar
                            </button>
                          </div>
                        )}
                      </div>
                      <div
                        className="avaliacao-resultado-box"
                        onClick={onAvaliacaoResultadoClick}
                        dangerouslySetInnerHTML={{ __html: resultadoAvaliacaoHtml }}
                      />
                    </div>
                  ) : null}
                </div>
              </>
            ) : null}

            {activeInnerTab === 'avaliacao_massa' ? (
              <div className="empty-box">Módulo em desenvolvimento.</div>
            ) : null}
          </div>
        </SectionBlock>
      ) : null}

      <LoadingOverlay show={loading} label="Processando dados..." />
      {error ? <div className="error-line">{error}</div> : null}
    </div>
  )
}
