"use client"

import type { JSX } from "react"
import { useEffect, useMemo, useState } from "react"
import { BarChart3 } from "lucide-react"
import { useTranslations } from "next-intl"
import { useQueryState, parseAsString } from "nuqs"

import { ChartCardShell } from "@/shared/components/charts/chart-card-shell"
import { TrendLineChart } from "@/shared/components/charts/trend-line-chart"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/shared/components/ui/select"
import { formatDate } from "@/shared/lib/utils"
import type { ClassAverageTrendResult } from "../types"
import type { StudentGradeSummary } from "../types"

interface GradeTrendCardProps {
  summary: StudentGradeSummary
  /** v3-P2-2: 班级平均趋势数据，传入后会在趋势图中叠加对比线 */
  classAverageData?: ClassAverageTrendResult | null
}

export function GradeTrendCard({ summary, classAverageData }: GradeTrendCardProps): JSX.Element {
  const t = useTranslations("grades")
  // v3-P3-4: 日期范围选择器，通过 URL 参数持久化
  const [trendRange, setTrendRange] = useQueryState(
    "trendRange",
    parseAsString.withDefault("all"),
  )

  // v3-P3-4: 在 useEffect 中计算日期截止时间，避免在渲染阶段调用 Date.now()
  const [cutoff, setCutoff] = useState<number | null>(null)
  useEffect(() => {
    const days = trendRange === "all" ? null : Number(trendRange)
    const next =
      days !== null && Number.isFinite(days) && days > 0
        ? Date.now() - days * 24 * 60 * 60 * 1000
        : null
    // eslint-disable-next-line react-hooks/set-state-in-effect -- 日期范围变更时需重新计算截止时间戳
    setCutoff(next)
  }, [trendRange])

  const { chartData, hasClassAverage } = useMemo(() => {
    // v3-P3-4: 根据日期范围筛选记录
    const records =
      cutoff !== null
        ? summary.records.filter((r) => {
            const time = new Date(r.createdAt).getTime()
            return !Number.isNaN(time) && time >= cutoff
          })
        : summary.records

    // 学生个人趋势：按时间升序
    const studentPoints = [...records]
      .sort((a, b) => {
        const timeA = new Date(a.createdAt).getTime()
        const timeB = new Date(b.createdAt).getTime()
        if (Number.isNaN(timeA) && Number.isNaN(timeB)) return 0
        if (Number.isNaN(timeA)) return 1
        if (Number.isNaN(timeB)) return -1
        return timeA - timeB
      })
      .map((r) => ({
        title: r.title,
        // P3 修复：添加 fullScore > 0 校验，避免除零
        score: r.fullScore > 0 ? Math.round((r.score / r.fullScore) * 100) : 0,
        fullTitle: r.title,
        submittedAt: formatDate(r.createdAt),
        rawScore: r.score,
        maxScore: r.fullScore,
      }))

    // v3-P2-2: 合并班级平均数据（按 title 对齐）
    const classAvgByTitle = new Map<string, number>()
    if (classAverageData?.points?.length) {
      for (const p of classAverageData.points) {
        classAvgByTitle.set(p.title, p.averageScore)
      }
    }

    // 将班级平均分合并到 chartData（缺失的 title 不显示对比点）
    const merged = studentPoints.map((p) => ({
      ...p,
      classAverage: classAvgByTitle.has(p.title)
        ? classAvgByTitle.get(p.title)
        : undefined,
    }))

    return {
      chartData: merged,
      hasClassAverage: classAvgByTitle.size > 0,
    }
  }, [summary.records, classAverageData, cutoff])

  const hasData = chartData.length > 0

  // v3-P2-2: 动态构建 series（有班级平均时叠加第二条线）
  const series = hasClassAverage
    ? [
        {
          dataKey: "score",
          name: t("chart.scorePercent"),
          color: "hsl(var(--primary))",
          dotRadius: 4,
          activeDotRadius: 6,
        },
        {
          dataKey: "classAverage",
          name: t("chart.classAverage"),
          color: "hsl(var(--muted-foreground))",
          dotRadius: 3,
          activeDotRadius: 5,
        },
      ]
    : [
        {
          dataKey: "score",
          name: t("chart.scorePercent"),
          color: "hsl(var(--primary))",
          dotRadius: 4,
          activeDotRadius: 6,
        },
      ]

  return (
    <ChartCardShell
      title={t("analytics.trend")}
      icon={BarChart3}
      iconClassName="text-muted-foreground"
      isEmpty={!hasData}
      emptyTitle={t("trend.empty")}
      emptyDescription={t("trendCard.emptyDescription")}
      emptyClassName="h-64"
      action={
        <Select value={trendRange} onValueChange={setTrendRange}>
          <SelectTrigger
            className="w-32"
            aria-label={t("trendCard.rangeAriaLabel")}
          >
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="all">{t("trendRange.all")}</SelectItem>
            <SelectItem value="7">{t("trendRange.days7")}</SelectItem>
            <SelectItem value="30">{t("trendRange.days30")}</SelectItem>
            <SelectItem value="90">{t("trendRange.days90")}</SelectItem>
          </SelectContent>
        </Select>
      }
    >
      <div
        className="rounded-md border bg-card p-4"
        role="img"
        aria-label={
          hasData
            ? t("trendCard.ariaLabelNonEmpty", { count: chartData.length })
            : t("trendCard.ariaLabelEmpty")
        }
      >
        <TrendLineChart
          data={chartData}
          series={series}
          heightClassName="h-60"
          margin={{ left: 12, right: 12, top: 12, bottom: 12 }}
          yWidth={30}
          tooltipClassName="w-52"
        />
      </div>
    </ChartCardShell>
  )
}
