import { useState } from 'react'
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from 'recharts'

import {
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from '@/components/ui/chart'
import type { ChartConfig } from '@/components/ui/chart'
import { Toggle } from '@/components/ui/toggle'
import { t } from '@/lib/i18n'
import type { HistoryPoint } from '@/pages/Seo/types'

type Metric = 'position' | 'impressions' | 'clicks'

const METRICS: Metric[] = ['position', 'impressions', 'clicks']

/** El color de cada serie. Lo único de la configuración que no es texto. */
const COLORS: Record<Metric, string> = {
  position: 'var(--chart-1)',
  impressions: 'var(--chart-2)',
  clicks: 'var(--chart-3)',
}

/**
 * La configuración del gráfico, armada **al dibujar**.
 *
 * Los rótulos son texto de pantalla —el globo los muestra— así que salen del
 * catálogo, y `t()` no se puede llamar a nivel de módulo: eso corre al importar,
 * cuando el catálogo del idioma todavía no está instalado. Estaban escritos
 * sueltos en inglés y era la única prosa del módulo fuera del catálogo.
 */
function config(): ChartConfig {
  return Object.fromEntries(
    METRICS.map((metric) => [
      metric,
      { label: t(`seo.column.${metric}` as 'seo.column.position'), color: COLORS[metric] },
    ])
  )
}

/**
 * La evolución diaria de una consulta.
 *
 * Las métricas se encienden y apagan porque no comparten escala: las
 * impresiones se cuentan por centenas y la posición va de 1 a 100, así que
 * dibujarlas juntas en un mismo eje aplasta una de las dos contra el borde. Por
 * eso hay dos ejes y por eso arranca mostrando sólo la posición, que es la
 * pregunta con la que se entra acá.
 *
 * **El eje de posición va invertido.** En Google el 1 es el mejor lugar, así que
 * con el eje natural una mejora se dibujaría como una caída, que es exactamente
 * lo contrario de lo que pasó.
 */
export function KeywordChart({ history }: { history: HistoryPoint[] }) {
  const [active, setActive] = useState<Metric[]>(['position'])

  // Nunca se apagan todas: un gráfico sin una sola serie es un marco vacío que
  // se lee como un error de carga.
  function toggle(metric: Metric) {
    setActive((current) => {
      if (!current.includes(metric)) return [...current, metric]
      if (current.length === 1) return current
      return current.filter((item) => item !== metric)
    })
  }

  return (
    <div className="flex flex-col gap-3">
      <div className="flex flex-wrap gap-2">
        {METRICS.map((metric) => (
          <Toggle
            key={metric}
            size="sm"
            variant="outline"
            pressed={active.includes(metric)}
            onPressedChange={() => toggle(metric)}
          >
            {t(`seo.column.${metric}` as 'seo.column.position')}
          </Toggle>
        ))}
      </div>

      <ChartContainer config={config()} className="aspect-auto h-64 w-full">
        <LineChart data={history} accessibilityLayer margin={{ left: 4, right: 4 }}>
          <CartesianGrid vertical={false} />
          <XAxis
            dataKey="date"
            tickLine={false}
            axisLine={false}
            tickMargin={8}
            minTickGap={24}
          />
          {active.includes('position') ? (
            <YAxis
              yAxisId="position"
              reversed
              tickLine={false}
              axisLine={false}
              width={36}
              allowDecimals={false}
            />
          ) : null}
          {active.some((metric) => metric !== 'position') ? (
            <YAxis
              yAxisId="counts"
              orientation="right"
              tickLine={false}
              axisLine={false}
              width={44}
            />
          ) : null}
          <ChartTooltip content={<ChartTooltipContent />} />
          {active.map((metric) => (
            <Line
              key={metric}
              yAxisId={metric === 'position' ? 'position' : 'counts'}
              dataKey={metric}
              type="monotone"
              stroke={`var(--color-${metric})`}
              strokeWidth={2}
              dot={false}
              // Un día sin dato deja un hueco y no una línea recta: Google omite
              // las consultas poco frecuentes, así que unir los extremos
              // dibujaría una continuidad que nadie observó.
              connectNulls={false}
            />
          ))}
        </LineChart>
      </ChartContainer>
    </div>
  )
}
