"use client";

/**
 * Attendance 统计页 - 班级考勤统计 + 趋势图 + 班级对比 + 学生预警
 *
 * 数据来源（P7 扩展，MSW mock）：
 * - GraphQL AttendanceStatsQuery：班级考勤统计（含 30 天趋势）
 * - GraphQL AttendanceClassComparisonQuery：5 班级出勤率对比
 * - GraphQL AttendanceWarningsQuery：学生考勤预警（出勤率 < 90%）
 * - GraphQL ClassesQuery：班级下拉选项
 *
 * SVG 图表参考 grades/analytics/charts.tsx 模式（var(--color-*) 语义令牌）
 *
 * 维护者：ai13（teacher-portal）
 */

import { useState, useMemo } from "react";
import { useQuery } from "urql";
import Link from "next/link";
import { Loading, Empty } from "@edu/ui-components";
import { ClassesQuery } from "@/lib/graphql";
import type { Class } from "@/lib/graphql";
import {
  AttendanceStatsQuery,
  AttendanceClassComparisonQuery,
  AttendanceWarningsQuery,
} from "@/lib/graphql-p7-admin";
import type {
  AttendanceStats,
  AttendanceTrendPoint,
  AttendanceClassComparison,
  AttendanceWarning,
} from "@/lib/graphql-p7-admin";

function dateMinusDays(days: number): string {
  const d = new Date();
  d.setDate(d.getDate() - days);
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}

function todayStr(): string {
  return dateMinusDays(0);
}

const RANGE_PRESETS: { label: string; days: number }[] = [
  { label: "近 7 天", days: 7 },
  { label: "近 14 天", days: 14 },
  { label: "近 30 天", days: 30 },
];

// ============ 趋势折线图（30 天每日出勤率） ============

const TREND_PADDING = { top: 24, right: 24, bottom: 36, left: 36 };
const TREND_W = 720;
const TREND_H = 220;

function TrendLineChart({ data }: { data: AttendanceTrendPoint[] }): React.ReactNode {
  if (data.length === 0) {
    return <p className="text-sm text-ink-muted">暂无趋势数据</p>;
  }
  const innerW = TREND_W - TREND_PADDING.left - TREND_PADDING.right;
  const innerH = TREND_H - TREND_PADDING.top - TREND_PADDING.bottom;
  const yMax = 100;
  const yMin = 0;
  const yRange = yMax - yMin;
  const xStep = data.length > 1 ? innerW / (data.length - 1) : 0;

  const toPoint = (value: number, i: number) => ({
    x: TREND_PADDING.left + i * xStep,
    y: TREND_PADDING.top + innerH - ((value - yMin) / yRange) * innerH,
  });

  const buildPath = (key: "presentRate" | "lateRate" | "absentRate") =>
    data
      .map((d, i) => {
        const p = toPoint(d[key], i);
        return `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`;
      })
      .join(" ");

  const gridLines = [0, 50, 100].map((v) => {
    const ratio = 1 - (v - yMin) / yRange;
    return { y: TREND_PADDING.top + innerH * ratio, value: v };
  });

  const lineColor = (key: "presentRate" | "lateRate" | "absentRate") =>
    key === "presentRate"
      ? "var(--color-accent)"
      : key === "lateRate"
        ? "var(--color-warning)"
        : "var(--color-danger)";

  // X 轴标签最多显示 6 个
  const labelStep = Math.max(1, Math.ceil(data.length / 6));

  return (
    <svg
      viewBox={`0 0 ${TREND_W} ${TREND_H}`}
      className="w-full border border-rule rounded-card bg-surface"
      role="img"
      aria-label="考勤趋势折线图"
    >
      {gridLines.map((g, i) => (
        <g key={`grid-${i}`}>
          <line
            x1={TREND_PADDING.left}
            y1={g.y}
            x2={TREND_W - TREND_PADDING.right}
            y2={g.y}
            stroke="var(--color-rule)"
            strokeWidth={1}
            strokeDasharray="3 3"
          />
          <text
            x={TREND_PADDING.left - 8}
            y={g.y + 4}
            textAnchor="end"
            fontSize="11"
            fontFamily="var(--font-family-mono)"
            fill="var(--color-ink-muted)"
          >
            {g.value}
          </text>
        </g>
      ))}
      {(["absentRate", "lateRate", "presentRate"] as const).map((key) => (
        <g key={key}>
          <path
            d={buildPath(key)}
            fill="none"
            stroke={lineColor(key)}
            strokeWidth={key === "presentRate" ? 2.5 : 1.5}
            strokeDasharray={key === "presentRate" ? undefined : "4 3"}
            strokeLinecap="round"
            strokeLinejoin="round"
          />
          {data.map((d, i) => {
            const p = toPoint(d[key], i);
            return (
              <circle
                key={`${key}-${i}`}
                cx={p.x}
                cy={p.y}
                r={key === "presentRate" ? 3 : 2}
                fill={lineColor(key)}
                stroke="var(--bg-paper)"
                strokeWidth={1}
              />
            );
          })}
        </g>
      ))}
      {data.map((d, i) =>
        i % labelStep === 0 ? (
          <text
            key={`x-${i}`}
            x={TREND_PADDING.left + i * xStep}
            y={TREND_H - TREND_PADDING.bottom + 18}
            textAnchor="middle"
            fontSize="10"
            fontFamily="var(--font-family-sans)"
            fill="var(--color-ink-muted)"
          >
            {d.date.slice(5)}
          </text>
        ) : null,
      )}
    </svg>
  );
}

// ============ 班级对比柱图 ============

const CMP_W = 480;
const CMP_H = 200;
const CMP_PAD = { top: 24, right: 16, bottom: 48, left: 36 };

function ClassComparisonChart({
  data,
}: {
  data: AttendanceClassComparison[];
}): React.ReactNode {
  if (data.length === 0) {
    return <p className="text-sm text-ink-muted">暂无班级对比数据</p>;
  }
  const maxRate = 100;
  const innerW = CMP_W - CMP_PAD.left - CMP_PAD.right;
  const innerH = CMP_H - CMP_PAD.top - CMP_PAD.bottom;
  const barW = innerW / data.length;

  return (
    <svg
      viewBox={`0 0 ${CMP_W} ${CMP_H}`}
      className="w-full border border-rule rounded-card bg-surface"
      role="img"
      aria-label="班级考勤对比柱图"
    >
      {[0, 0.5, 1].map((ratio, i) => {
        const y = CMP_PAD.top + innerH * ratio;
        const value = Math.round(maxRate * (1 - ratio));
        return (
          <g key={`grid-${i}`}>
            <line
              x1={CMP_PAD.left}
              y1={y}
              x2={CMP_W - CMP_PAD.right}
              y2={y}
              stroke="var(--color-rule)"
              strokeWidth={1}
              strokeDasharray="3 3"
            />
            <text
              x={CMP_PAD.left - 8}
              y={y + 4}
              textAnchor="end"
              fontSize="11"
              fontFamily="var(--font-family-mono)"
              fill="var(--color-ink-muted)"
            >
              {value}%
            </text>
          </g>
        );
      })}
      {data.map((item, i) => {
        const barH = (item.presentRate / maxRate) * innerH;
        const x = CMP_PAD.left + i * barW + barW * 0.2;
        const y = CMP_PAD.top + innerH - barH;
        const w = barW * 0.6;
        return (
          <g key={item.classId}>
            <rect
              x={x}
              y={y}
              width={w}
              height={Math.max(0, barH)}
              fill="var(--color-accent)"
              rx={3}
            />
            <text
              x={x + w / 2}
              y={y - 6}
              textAnchor="middle"
              fontSize="11"
              fontFamily="var(--font-family-mono)"
              fontWeight="600"
              fill="var(--color-ink)"
            >
              {item.presentRate}%
            </text>
            <text
              x={x + w / 2}
              y={CMP_H - CMP_PAD.bottom + 14}
              textAnchor="middle"
              fontSize="10"
              fontFamily="var(--font-family-sans)"
              fill="var(--color-ink-muted)"
            >
              {item.className}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

export default function AttendanceStatsPage(): React.ReactNode {
  const [classId, setClassId] = useState("");
  const [rangeDays, setRangeDays] = useState(7);

  const [classesResult] = useQuery({ query: ClassesQuery });
  const classes: Class[] = classesResult.data?.classes ?? [];
  const firstClassId = classes[0]?.id ?? "";
  const targetClassId = classId || firstClassId;

  const startDate = useMemo(() => dateMinusDays(rangeDays - 1), [rangeDays]);
  const endDate = useMemo(() => todayStr(), []);

  const [statsResult] = useQuery({
    query: AttendanceStatsQuery,
    variables: { classId: targetClassId, startDate, endDate },
    pause: !targetClassId,
  });

  const [cmpResult] = useQuery({
    query: AttendanceClassComparisonQuery,
    variables: { startDate, endDate },
  });

  const [warningsResult] = useQuery({
    query: AttendanceWarningsQuery,
    variables: { classId: targetClassId, startDate, endDate },
    pause: !targetClassId,
  });

  const stats: AttendanceStats | undefined = statsResult.data?.attendanceStats;
  const comparisons: AttendanceClassComparison[] =
    cmpResult.data?.attendanceClassComparison ?? [];
  const warnings: AttendanceWarning[] =
    warningsResult.data?.attendanceWarnings ?? [];

  return (
    <div className="px-10 py-10">
      <header className="mb-8 flex items-baseline justify-between">
        <div>
          <p className="mb-2">
            <Link
              href="/attendance"
              className="text-tiny uppercase tracking-wide text-ink-muted hover:opacity-70"
            >
              ← 返回考勤记录
            </Link>
          </p>
          <h1 className="text-3xl font-serif text-ink">考勤统计</h1>
          <p className="mt-1 text-sm text-ink-muted">
            GraphQL AttendanceStatsQuery · 班级统计 + 趋势 + 对比 + 预警（P7 扩展，MSW mock）
          </p>
        </div>
      </header>

      <div className="rule-thin mb-8" />

      {/* 班级 + 时间范围筛选 */}
      <section className="mb-8">
        <div className="grid grid-cols-2 gap-6 mb-4">
          <div>
            <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
              班级
            </label>
            <select
              value={targetClassId}
              onChange={(e) => setClassId(e.target.value)}
              className="w-full px-3 py-2 bg-transparent border-b border-rule text-sm font-sans text-ink focus:outline-none focus:border-accent"
            >
              <option value="">请选择班级</option>
              {classes.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </select>
          </div>
          <div>
            <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
              时间范围
            </label>
            <div className="flex items-center gap-2 flex-wrap">
              {RANGE_PRESETS.map((p) => {
                const active = rangeDays === p.days;
                return (
                  <button
                    key={p.days}
                    type="button"
                    onClick={() => setRangeDays(p.days)}
                    className={`px-3 py-1 text-tiny uppercase tracking-wide rounded-button border transition-colors ${
                      active
                        ? "bg-accent text-ink-on-accent border-accent"
                        : "bg-transparent text-ink-muted border-rule hover:text-ink"
                    }`}
                  >
                    {p.label}
                  </button>
                );
              })}
            </div>
          </div>
        </div>
        <p className="text-tiny text-ink-muted">
          统计区间：{startDate} ~ {endDate}
        </p>
      </section>

      {classesResult.fetching || statsResult.fetching ? (
        <Loading lines={6} />
      ) : statsResult.error ? (
        <div className="mark-left mb-4 py-2 border-l-2 border-danger pl-md">
          <p className="text-sm px-3 text-danger">
            加载失败：{statsResult.error.message}
          </p>
        </div>
      ) : !stats ? (
        <Empty title="暂无统计数据" description="请选择班级和时间范围" />
      ) : (
        <>
          {/* 5 个统计卡片 */}
          <section className="mb-10">
            <h2 className="text-xl font-serif text-ink mb-4">
              {stats.className} · 统计摘要
            </h2>
            <div className="rule-thin mb-6" />
            <dl className="grid grid-cols-5 gap-4">
              <div className="p-4 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  出勤率
                </dt>
                <dd className="mt-2 text-3xl font-serif text-accent">
                  {stats.presentRate.toFixed(1)}%
                </dd>
              </div>
              <div className="p-4 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  迟到率
                </dt>
                <dd className="mt-2 text-3xl font-serif text-warning">
                  {stats.lateRate.toFixed(1)}%
                </dd>
              </div>
              <div className="p-4 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  早退率
                </dt>
                <dd className="mt-2 text-3xl font-serif text-warning">
                  {stats.earlyLeaveRate.toFixed(1)}%
                </dd>
              </div>
              <div className="p-4 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  请假率
                </dt>
                <dd className="mt-2 text-3xl font-serif text-ink">
                  {stats.leaveRate.toFixed(1)}%
                </dd>
              </div>
              <div className="p-4 border border-rule rounded-card">
                <dt className="text-tiny uppercase tracking-wide text-ink-muted">
                  预警学生
                </dt>
                <dd className="mt-2 text-3xl font-serif text-danger">
                  {stats.warningCount}
                </dd>
              </div>
            </dl>
            <p className="mt-4 text-tiny text-ink-muted">
              共 {stats.totalRecords} 条记录 · 出勤 {stats.presentCount} ·
              迟到 {stats.lateCount} · 早退 {stats.earlyLeaveCount} ·
              请假 {stats.leaveCount} · 缺勤 {stats.absentCount}
            </p>
          </section>

          {/* 趋势折线图 */}
          <section className="mb-10">
            <h2 className="text-xl font-serif text-ink mb-4">
              出勤率趋势（{stats.trend.length} 天）
            </h2>
            <div className="rule-thin mb-4" />
            <TrendLineChart data={stats.trend} />
            <div className="mt-3 flex items-center gap-4 text-tiny text-ink-muted">
              <span className="inline-flex items-center gap-1">
                <span
                  className="inline-block w-3 h-0.5"
                  style={{ background: "var(--color-accent)" }}
                />
                出勤率
              </span>
              <span className="inline-flex items-center gap-1">
                <span
                  className="inline-block w-3 h-0.5"
                  style={{
                    background: "var(--color-warning)",
                    borderTop: "1px dashed var(--color-warning)",
                  }}
                />
                迟到率
              </span>
              <span className="inline-flex items-center gap-1">
                <span
                  className="inline-block w-3 h-0.5"
                  style={{ background: "var(--color-danger)" }}
                />
                缺勤率
              </span>
            </div>
          </section>

          {/* 班级对比柱图 */}
          <section className="mb-10">
            <h2 className="text-xl font-serif text-ink mb-4">班级出勤率对比</h2>
            <div className="rule-thin mb-4" />
            <ClassComparisonChart data={comparisons} />
          </section>

          {/* 学生预警表 */}
          <section>
            <h2 className="text-xl font-serif text-ink mb-4">
              学生考勤预警
              <span className="ml-2 text-sm font-sans text-ink-muted">
                出勤率 &lt; 90% · 共 {warnings.length} 名
              </span>
            </h2>
            <div className="rule-thin mb-4" />
            {warnings.length === 0 ? (
              <Empty title="暂无预警" description="所有学生出勤率均达标" />
            ) : (
              <div className="border border-rule rounded-card overflow-hidden">
                <table className="w-full text-sm">
                  <thead className="bg-subtle">
                    <tr>
                      <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                        学号
                      </th>
                      <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                        姓名
                      </th>
                      <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted">
                        班级
                      </th>
                      <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted w-32">
                        出勤率
                      </th>
                      <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted w-24">
                        缺勤次数
                      </th>
                      <th className="px-4 py-3 text-left text-tiny uppercase tracking-wide text-ink-muted w-24">
                        迟到次数
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    {warnings.map((w) => (
                      <tr key={w.studentId} className="border-t border-rule">
                        <td className="px-4 py-3 font-mono text-tiny text-ink-muted">
                          {w.studentNo}
                        </td>
                        <td className="px-4 py-3 font-serif text-ink">
                          {w.studentName}
                        </td>
                        <td className="px-4 py-3 text-ink-muted">
                          {w.className}
                        </td>
                        <td className="px-4 py-3 font-serif text-danger">
                          {w.presentRate.toFixed(1)}%
                        </td>
                        <td className="px-4 py-3 font-mono text-tiny text-ink-muted">
                          {w.absentCount}
                        </td>
                        <td className="px-4 py-3 font-mono text-tiny text-ink-muted">
                          {w.lateCount}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </section>
        </>
      )}
    </div>
  );
}
