'use client'

import { useMemo, useState } from 'react'
import {
  CartesianGrid,
  Line,
  LineChart,
  ReferenceDot,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
  Bar,
  BarChart,
} from 'recharts'
import type { GenericFormulaSim } from '@/lib/interactive-page'
import { parseSimExpr } from '@/lib/interactive-page/sim-eval'
import { intentColor } from '@/lib/interactive-demo/intent-colors'
import { useDarkMode } from '@/components/interactive-demo/demo-speak'
import { SimHeading, SimOutputCard, SimSlider } from './sim-controls'

const CURVE_SAMPLES = 60

/** Generic slider-driven formula simulator (safe exprs, no eval). */
export function GenericFormulaView({
  sim,
  lang,
}: {
  sim: GenericFormulaSim
  lang: string
}) {
  const fr = lang.startsWith('fr')
  const dark = useDarkMode()
  const [values, setValues] = useState<Record<string, number>>(() => {
    const env: Record<string, number> = {}
    for (const p of sim.params) env[p.id] = p.defaultValue
    return env
  })

  const compiled = useMemo(
    () =>
      sim.computed.map((c) => ({
        def: c,
        parsed: parseSimExpr(c.expr),
      })),
    [sim.computed]
  )

  const results = useMemo(() => {
    const env = { ...values }
    const out: Record<string, number> = {}
    for (const c of compiled) {
      const v = 'message' in c.parsed ? NaN : c.parsed.evaluate(env)
      env[c.def.id] = v
      out[c.def.id] = v
    }
    return out
  }, [compiled, values])

  const visual = sim.visual
  const curve = useMemo(() => {
    if (visual.kind !== 'curve') return null
    const xParam = sim.params.find((p) => p.id === visual.xParamId)
    const parsed = parseSimExpr(visual.expr)
    if (!xParam || 'message' in parsed) return null
    const pts: { x: number; y: number }[] = []
    for (let i = 0; i <= CURVE_SAMPLES; i++) {
      const x = xParam.min + ((xParam.max - xParam.min) * i) / CURVE_SAMPLES
      const y = parsed.evaluate({ ...values, [xParam.id]: x })
      pts.push({ x: Number(x.toFixed(4)), y: Number.isFinite(y) ? Number(y.toFixed(6)) : 0 })
    }
    return { pts, xParam, currentX: values[xParam.id], currentY: parsed.evaluate(values) }
  }, [visual, sim.params, values])

  const accent = intentColor('highlight', dark)
  const gridStroke = dark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)'

  return (
    <div>
      {sim.intro ? (
        <p className="mb-4 text-[15px] leading-relaxed text-muted-foreground">
          {sim.intro}
        </p>
      ) : null}
      <div className="grid gap-5 md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]">
        <div className="space-y-3">
          <SimHeading>{fr ? 'Paramètres' : 'Parameters'}</SimHeading>
          <div className="space-y-2">
            {sim.params.map((p) => (
              <SimSlider
                key={p.id}
                symbol={p.symbol}
                label={p.label}
                unit={p.unit}
                min={p.min}
                max={p.max}
                step={p.step}
                value={values[p.id]}
                intent={p.intent}
                onChange={(v) => setValues((s) => ({ ...s, [p.id]: v }))}
              />
            ))}
          </div>
        </div>

        <div className="space-y-3">
          <SimHeading>{fr ? 'Résultats' : 'Results'}</SimHeading>
          {sim.visual.kind === 'gauges' ? (
            <div className="space-y-2">
              {sim.computed.map((c) => {
                const v = results[c.id]
                const maxRef = Math.max(
                  ...sim.computed.map((o) => Math.abs(results[o.id] || 0)),
                  1
                )
                const color = intentColor(c.intent, dark)
                return (
                  <div key={c.id} className="rounded-xl border border-border/50 bg-background/70 px-3 py-2">
                    <div className="flex items-baseline justify-between text-xs">
                      <span className="text-muted-foreground">{c.label}</span>
                      <span className="font-semibold tabular-nums" style={{ color }}>
                        {Number.isFinite(v) ? v.toFixed(2) : '—'}
                        {c.unit ? ` ${c.unit}` : ''}
                      </span>
                    </div>
                    <div className="mt-1.5 h-2 overflow-hidden rounded-full bg-muted/60">
                      <div
                        className="h-full rounded-full transition-[width] duration-150"
                        style={{
                          width: `${Math.min(100, (Math.abs(v || 0) / maxRef) * 100)}%`,
                          backgroundColor: color,
                        }}
                      />
                    </div>
                  </div>
                )
              })}
            </div>
          ) : null}

          {sim.visual.kind === 'bars' ? (
            <div className="h-48 w-full">
              <ResponsiveContainer width="100%" height="100%">
                <BarChart
                  data={sim.computed.map((c) => ({
                    name: c.label,
                    value: Number.isFinite(results[c.id]) ? results[c.id] : 0,
                  }))}
                  margin={{ top: 8, right: 8, left: 0, bottom: 4 }}
                >
                  <CartesianGrid strokeDasharray="3 3" stroke={gridStroke} />
                  <XAxis dataKey="name" tick={{ fontSize: 10 }} axisLine={false} tickLine={false} />
                  <YAxis tick={{ fontSize: 10 }} width={40} axisLine={false} tickLine={false} />
                  <Tooltip />
                  <Bar dataKey="value" fill={accent} radius={[4, 4, 0, 0]} isAnimationActive={false} />
                </BarChart>
              </ResponsiveContainer>
            </div>
          ) : null}

          {sim.visual.kind === 'curve' && curve ? (
            <div className="h-48 w-full">
              <ResponsiveContainer width="100%" height="100%">
                <LineChart data={curve.pts} margin={{ top: 8, right: 8, left: 0, bottom: 4 }}>
                  <CartesianGrid strokeDasharray="3 3" stroke={gridStroke} />
                  <XAxis
                    dataKey="x"
                    type="number"
                    domain={[curve.xParam.min, curve.xParam.max]}
                    tick={{ fontSize: 10 }}
                    axisLine={false}
                    tickLine={false}
                    tickFormatter={(v: number) => String(Math.round(v))}
                  />
                  <YAxis tick={{ fontSize: 10 }} width={40} axisLine={false} tickLine={false} />
                  <Tooltip />
                  <Line type="monotone" dataKey="y" stroke={accent} strokeWidth={2.5} dot={false} isAnimationActive={false} />
                  {Number.isFinite(curve.currentY) ? (
                    <ReferenceDot x={curve.currentX} y={curve.currentY} r={5} fill={accent} stroke="none" />
                  ) : null}
                </LineChart>
              </ResponsiveContainer>
            </div>
          ) : null}

          <div className="grid grid-cols-2 gap-2">
            {sim.computed.map((c) => (
              <SimOutputCard
                key={c.id}
                symbol={c.symbol}
                label={c.label}
                value={results[c.id]}
                unit={c.unit}
                intent={c.intent}
              />
            ))}
          </div>
        </div>
      </div>
      {sim.disclaimer ? (
        <p className="mt-3 text-xs italic text-muted-foreground">{sim.disclaimer}</p>
      ) : null}
    </div>
  )
}
