"use client"
import { use, useEffect, useMemo, useState } from 'react'
import Link from 'next/link'
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  BarElement,
  Tooltip,
  Legend,
} from 'chart.js'
import { Line, Bar, Scatter } from 'react-chartjs-2'

ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, BarElement, Tooltip, Legend)

type Detail = {
  id: string
  timestamp: string
  code: number[]
  fit?: { a: number; b: number }
  sampleCount: number
  duration: number
  stats: {
    codeMin: number
    codeMax: number
    codeAvg: number
    forceMin?: number
    forceMax?: number
    forceAvg?: number
  }
}

function toFixed(n: number | undefined | null, d = 3) {
  if (n == null || Number.isNaN(n)) return '-'
  return n.toFixed(d)
}

export default function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = use(params)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [rec, setRec] = useState<Detail | null>(null)
  const [emaAlpha, setEmaAlpha] = useState(0.01)
  const [enableEma, setEnableEma] = useState(true)

  useEffect(() => {
    const controller = new AbortController()
    async function run() {
      setLoading(true)
      setError(null)
      try {
        const res = await fetch(`/api/records/${id}`, { signal: controller.signal })
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        const j = await res.json()
        setRec(j)
      } catch (e) {
        // @ts-expect-error any
        if (e.name !== 'AbortError') setError(e.message || '加载失败')
      } finally {
        setLoading(false)
      }
    }
    run()
    return () => controller.abort()
  }, [id])

  const timeAxis = useMemo(() => {
    if (!rec) return [] as number[]
    const step = rec.sampleCount > 0 ? (rec.duration * 1000) / rec.sampleCount : 0
    return Array.from({ length: rec.sampleCount }, (_, i) => +(i * step).toFixed(3))
  }, [rec])

  const smoothedCode = useMemo(() => {
    if (!rec || !enableEma) return rec?.code || []
    return applyEMA(rec.code, emaAlpha)
  }, [rec, enableEma, emaAlpha])

  const forceSeries = useMemo(() => {
    if (!rec?.fit) return undefined
    const { a, b } = rec.fit
    const dataToUse = enableEma ? smoothedCode : rec.code
    return dataToUse.map((c) => a * c + b)
  }, [rec, enableEma, smoothedCode])

  const codeHistogram = useMemo(() => {
    const dataToUse = enableEma ? smoothedCode : (rec?.code || [])
    return buildHistogram(dataToUse, 30)
  }, [rec, enableEma, smoothedCode])
  const forceHistogram = useMemo(() => buildHistogram(forceSeries || [], 30), [forceSeries])

  return (
    <div className="min-h-screen bg-zinc-50 text-zinc-900 dark:bg-black dark:text-zinc-100">
      <div className="mx-auto max-w-6xl p-4 sm:p-6">
        <div className="mb-4 flex items-center justify-between">
          <div className="flex items-center gap-3">
            <Link href="/" className="rounded border px-3 py-1.5">← 返回</Link>
            <h1 className="text-xl font-semibold">记录 {rec?.id || id}</h1>
          </div>
          <div className="flex gap-2">
            <a
              href={`/api/export`}
              onClick={async (e) => {
                e.preventDefault()
                const body = JSON.stringify({ ids: [id], format: 'csv' as const })
                const res = await fetch('/api/export', { method: 'POST', headers: { 'content-type': 'application/json' }, body })
                const blob = await res.blob()
                const url = URL.createObjectURL(blob)
                const a = document.createElement('a')
                a.href = url
                a.download = `record-${id}.csv`
                a.click()
                URL.revokeObjectURL(url)
              }}
              className="rounded bg-zinc-900 px-3 py-1.5 text-white dark:bg-zinc-100 dark:text-black"
            >导出 CSV</a>
          </div>
        </div>

        {loading && <div className="rounded bg-zinc-200 p-4 dark:bg-zinc-800">加载中...</div>}
        {error && <div className="rounded bg-red-100 p-4 text-red-800">{error}</div>}
        {rec && (
          <div className="flex flex-col gap-6">
            <section className="grid grid-cols-1 gap-4 sm:grid-cols-3">
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="text-sm text-zinc-500">上传时间</div>
                <div className="mt-1 text-lg">{new Date(rec.timestamp).toLocaleString()}</div>
              </div>
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="text-sm text-zinc-500">采样</div>
                <div className="mt-1 text-lg">{rec.sampleCount} 点 · {rec.duration.toFixed(3)} s · {(rec.sampleCount / rec.duration).toFixed(2)} Hz</div>
              </div>
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="text-sm text-zinc-500">拟合</div>
                <div className="mt-1 text-lg">{rec.fit ? `y = ${rec.fit.a.toFixed(4)}x + ${rec.fit.b.toFixed(3)}` : '未拟合'}</div>
              </div>
            </section>

            <section className="grid grid-cols-1 gap-4 sm:grid-cols-3">
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="text-sm text-zinc-500">码值统计</div>
                <div className="mt-1 text-lg">[{rec.stats.codeMin} ~ {rec.stats.codeMax}] · 均值 {toFixed(rec.stats.codeAvg, 2)}</div>
              </div>
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="text-sm text-zinc-500">力值统计</div>
                <div className="mt-1 text-lg">{rec.fit ? `[${toFixed(rec.stats.forceMin, 2)} ~ ${toFixed(rec.stats.forceMax, 2)}] mN · 均值 ${toFixed(rec.stats.forceAvg, 2)}` : '—'}</div>
              </div>
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="text-sm text-zinc-500">峰峰值</div>
                <div className="mt-1 text-lg">码值 {rec.stats.codeMax - rec.stats.codeMin}{rec.fit && rec.stats.forceMax != null && rec.stats.forceMin != null ? ` · 力值 ${(rec.stats.forceMax - rec.stats.forceMin).toFixed(2)} mN` : ''}</div>
              </div>
            </section>

            <section className="rounded-lg border p-4 dark:border-zinc-800">
              <div className="mb-3 flex items-center justify-between">
                <div className="text-sm text-zinc-500">时序曲线</div>
                <div className="flex items-center gap-4">
                  <label className="flex items-center gap-2 text-sm">
                    <input
                      type="checkbox"
                      checked={enableEma}
                      onChange={(e) => setEnableEma(e.target.checked)}
                      className="rounded"
                    />
                    <span>EMA平滑</span>
                  </label>
                  {enableEma && (
                    <label className="flex items-center gap-2 text-sm">
                      <span>α:</span>
                      <input
                        type="range"
                        min="0.01"
                        max="1"
                        step="0.01"
                        value={emaAlpha}
                        onChange={(e) => setEmaAlpha(Number(e.target.value))}
                        className="w-24"
                      />
                      <span className="w-12 text-right">{emaAlpha.toFixed(2)}</span>
                    </label>
                  )}
                </div>
              </div>
              <Line
                data={{
                  labels: timeAxis,
                  datasets: [
                    {
                      type: 'line' as const,
                      label: '码值',
                      data: enableEma ? smoothedCode : rec.code,
                      borderColor: '#0ea5e9',
                      backgroundColor: 'rgba(14,165,233,0.2)',
                      borderWidth: 1.5,
                      yAxisID: 'yCode',
                      pointRadius: 0,
                    },
                    ...(rec.fit && forceSeries
                      ? [
                          {
                            type: 'line' as const,
                            label: '力值 (mN)',
                            data: forceSeries,
                            borderColor: '#22c55e',
                            backgroundColor: 'rgba(34,197,94,0.2)',
                            borderWidth: 1.5,
                            yAxisID: 'yForce',
                            pointRadius: 0,
                          },
                        ]
                      : []),
                  ],
                }}
                options={{
                  responsive: true,
                  interaction: { mode: 'index', intersect: false },
                  plugins: { legend: { position: 'top' as const } },
                  scales: {
                    x: { title: { display: true, text: '时间 (ms)' } },
                    yCode: { type: 'linear' as const, position: 'left' as const, title: { display: true, text: '码值' } },
                    yForce: { type: 'linear' as const, position: 'right' as const, title: { display: true, text: '力值 (mN)' }, grid: { drawOnChartArea: false } },
                  },
                }}
              />
            </section>

            <section className="grid grid-cols-1 gap-4 sm:grid-cols-2">
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="mb-3 text-sm text-zinc-500">码值分布直方图</div>
                <Bar
                  data={{
                    labels: codeHistogram.labels,
                    datasets: [
                      {
                        label: '频数',
                        data: codeHistogram.counts,
                        backgroundColor: 'rgba(14,165,233,0.3)',
                        borderColor: '#0ea5e9',
                      },
                    ],
                  }}
                  options={{ scales: { x: { title: { display: true, text: '码值' } }, y: { title: { display: true, text: '数量' } } } }}
                />
              </div>
              <div className="rounded-lg border p-4 dark:border-zinc-800">
                <div className="mb-3 text-sm text-zinc-500">线性度散点图</div>
                {rec.fit && forceSeries ? (
                  <Scatter
                    data={{
                      datasets: [
                        {
                          label: '码值 vs 力值',
                          data: (enableEma ? smoothedCode : rec.code).map((c, i) => ({ x: c, y: forceSeries[i] })),
                          backgroundColor: '#22c55e',
                        },
                      ],
                    }}
                    options={{
                      scales: {
                        x: { title: { display: true, text: '码值' } },
                        y: { title: { display: true, text: '力值 (mN)' } },
                      },
                      plugins: { legend: { display: false } },
                    }}
                  />
                ) : (
                  <div className="text-sm text-zinc-500">无拟合参数，无法绘制</div>
                )}
              </div>
            </section>
          </div>
        )}
      </div>
    </div>
  )
}

function applyEMA(data: number[], alpha: number): number[] {
  if (data.length === 0) return []
  const result: number[] = [data[0]]
  for (let i = 1; i < data.length; i++) {
    result.push(alpha * data[i] + (1 - alpha) * result[i - 1])
  }
  return result
}

function buildHistogram(values: number[], bins: number) {
  if (!values.length || bins <= 0) return { labels: [] as string[], counts: [] as number[] }
  let min = values[0]
  let max = values[0]
  for (const v of values) {
    if (v < min) min = v
    if (v > max) max = v
  }
  if (min === max) {
    return { labels: [min.toFixed(2)], counts: [values.length] }
  }
  const step = (max - min) / bins
  const edges = Array.from({ length: bins + 1 }, (_, i) => min + i * step)
  const counts = Array.from({ length: bins }, () => 0)
  for (const v of values) {
    let idx = Math.floor((v - min) / step)
    if (idx >= bins) idx = bins - 1
    if (idx < 0) idx = 0
    counts[idx]++
  }
  const labels = Array.from({ length: bins }, (_, i) => `${edges[i].toFixed(1)}~${edges[i + 1].toFixed(1)}`)
  return { labels, counts }
}
