"use client";

/**
 * 课标覆盖热力图页
 *
 * 数据来源（P7 扩展，MSW mock）：
 * - GraphQL LessonPlanHeatmapQuery：按教材 ID 拉取热力图（教材知识点 × 课案覆盖矩阵）
 *
 * 布局：
 * - 顶部：教材选择 select + 导出 CSV 按钮
 * - 热力图矩阵（X 轴：教材知识点，Y 轴：课案）
 * - 每个格子颜色深浅表示覆盖度（0-3：浅 → 深）
 * - SVG 实现，hover 显示 tooltip（知识点名/课案名/覆盖数）
 *
 * 维护者：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 { LessonPlanHeatmapQuery } from "@/lib/graphql-p7-advanced";
import type { LessonPlanHeatmap as HeatmapData } from "@/lib/graphql-p7-advanced";
import { listHeatmapTextbooks } from "@/mocks/fixtures/lesson-plan-heatmap";

/** 教材选项（mock：从 fixture 获取） */
const TEXTBOOK_OPTIONS = listHeatmapTextbooks();

/** SVG 布局常量 */
const CELL_W = 22;
const CELL_H = 26;
const LABEL_COL_W = 160; // Y 轴标签（课案名）宽度
const LABEL_ROW_H = 60; // X 轴标签（知识点名）高度
const HEADER_PADDING = 10;

/** 按覆盖度映射填充色（语义令牌变量，0 最浅，3 最深） */
function coverageColor(coverage: number): string {
  switch (coverage) {
    case 0:
      return "var(--color-surface)";
    case 1:
      return "var(--color-accent-soft, hsl(var(--accent-h) 60% 80%))";
    case 2:
      return "var(--color-accent-muted, hsl(var(--accent-h) 55% 65%))";
    case 3:
      return "var(--color-accent)";
    default:
      return "var(--color-surface)";
  }
}

/** 按 coverage 取浅色文字（深色格子用反色文字） */
function textColor(coverage: number): string {
  return coverage >= 2
    ? "var(--color-ink-on-accent)"
    : "var(--color-ink-muted)";
}

/** Tooltip 状态 */
interface TooltipState {
  kpName: string;
  planName: string;
  coverage: number;
  x: number;
  y: number;
}

export default function LessonPlanHeatmapPage(): React.ReactNode {
  const [textbookId, setTextbookId] = useState(
    TEXTBOOK_OPTIONS[0]?.textbookId ?? "",
  );

  const [result] = useQuery({
    query: LessonPlanHeatmapQuery,
    variables: { textbookId },
    pause: !textbookId,
  });

  const [tooltip, setTooltip] = useState<TooltipState | null>(null);

  const heatmap: HeatmapData | null = result.data?.lessonPlanHeatmap ?? null;

  // 构建 cell 查找 Map：`${kpId}|${planId}` → coverage
  const cellMap = useMemo(() => {
    const m = new Map<string, number>();
    if (heatmap) {
      for (const cell of heatmap.cells) {
        m.set(`${cell.kpId}|${cell.planId}`, cell.coverage);
      }
    }
    return m;
  }, [heatmap]);

  // SVG 尺寸
  const kpCount = heatmap?.knowledgePoints.length ?? 0;
  const planCount = heatmap?.lessonPlans.length ?? 0;
  const svgWidth = LABEL_COL_W + kpCount * CELL_W + HEADER_PADDING;
  const svgHeight = LABEL_ROW_H + planCount * CELL_H + HEADER_PADDING;

  /** 导出 CSV */
  const handleExportCsv = () => {
    if (!heatmap) return;
    const header = [
      "课案/知识点",
      ...heatmap.knowledgePoints.map((kp) => kp.name),
    ].join(",");
    const rows = heatmap.lessonPlans.map((plan) => {
      const cells = heatmap.knowledgePoints.map((kp) => {
        const cov = cellMap.get(`${kp.kpId}|${plan.planId}`) ?? 0;
        return String(cov);
      });
      return [plan.title, ...cells].join(",");
    });
    const csv = [header, ...rows].join("\n");
    // 添加 BOM 以支持 Excel 中文
    const blob = new Blob([`\uFEFF${csv}`], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `heatmap-${heatmap.textbookId}.csv`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  return (
    <div className="px-10 py-10">
      <header className="mb-8">
        <p className="mb-2">
          <Link
            href="/lesson-plans"
            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 LessonPlanHeatmapQuery · core-edu 域（P7 扩展，MSW mock）
        </p>
      </header>

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

      {/* 操作栏：教材选择 + 导出 CSV */}
      <section className="mb-6 flex items-end justify-between gap-4">
        <div>
          <label className="block text-tiny uppercase tracking-wide text-ink-muted mb-1">
            教材
          </label>
          <select
            value={textbookId}
            onChange={(e) => setTextbookId(e.target.value)}
            className="px-3 py-2 bg-transparent border border-rule rounded-button text-sm text-ink focus:outline-none"
          >
            {TEXTBOOK_OPTIONS.map((tb) => (
              <option key={tb.textbookId} value={tb.textbookId}>
                {tb.textbookTitle}（{tb.subject}）
              </option>
            ))}
          </select>
        </div>
        {heatmap && (
          <button
            type="button"
            onClick={handleExportCsv}
            className="px-4 py-2 text-sm text-ink bg-transparent border border-rule rounded-button hover:bg-subtle"
          >
            导出 CSV
          </button>
        )}
      </section>

      {result.fetching ? (
        <Loading lines={8} />
      ) : result.error ? (
        <div className="mark-left mb-4 py-2 border-l-2 border-danger pl-md">
          <p className="text-sm px-3 text-danger">
            加载失败：{result.error.message}
          </p>
        </div>
      ) : !heatmap ? (
        <Empty title="未找到热力图数据" description="请选择其他教材" />
      ) : heatmap.knowledgePoints.length === 0 ? (
        <Empty title="暂无知识点" description="该教材无知识点数据" />
      ) : (
        <section>
          {/* 图例 */}
          <div className="mb-4 flex items-center gap-4">
            <span className="text-tiny uppercase tracking-wide text-ink-muted">
              覆盖度
            </span>
            {[0, 1, 2, 3].map((c) => (
              <div key={c} className="flex items-center gap-2">
                <span
                  className="inline-block w-4 h-4 rounded-button"
                  style={{ background: coverageColor(c) }}
                />
                <span className="text-tiny text-ink-muted">{c} 课案</span>
              </div>
            ))}
          </div>

          {/* SVG 热力图（可滚动容器） */}
          <div
            className="relative overflow-auto border border-rule rounded-card bg-paper"
            style={{ maxHeight: "70vh" }}
            onMouseLeave={() => setTooltip(null)}
          >
            <svg
              width={svgWidth}
              height={svgHeight}
              role="img"
              aria-label={`${heatmap.textbookTitle} 课标覆盖热力图`}
            >
              {/* X 轴标签：知识点名（旋转 -60°） */}
              <g>
                {heatmap.knowledgePoints.map((kp, i) => {
                  const x = LABEL_COL_W + i * CELL_W + CELL_W / 2;
                  const y = LABEL_ROW_H - 8;
                  return (
                    <text
                      key={kp.kpId}
                      x={x}
                      y={y}
                      textAnchor="end"
                      fontSize="11"
                      fontFamily="var(--font-family-sans)"
                      fill="var(--color-ink-muted)"
                      transform={`rotate(-60, ${x}, ${y})`}
                    >
                      {kp.name}
                    </text>
                  );
                })}
              </g>

              {/* Y 轴标签：课案名 */}
              <g>
                {heatmap.lessonPlans.map((plan, j) => {
                  const y = LABEL_ROW_H + j * CELL_H + CELL_H / 2 + 4;
                  return (
                    <text
                      key={plan.planId}
                      x={LABEL_COL_W - 8}
                      y={y}
                      textAnchor="end"
                      fontSize="11"
                      fontFamily="var(--font-family-sans)"
                      fill="var(--color-ink)"
                    >
                      {plan.title}
                    </text>
                  );
                })}
              </g>

              {/* 单元格 */}
              <g>
                {heatmap.knowledgePoints.map((kp, i) =>
                  heatmap.lessonPlans.map((plan, j) => {
                    const cellX = LABEL_COL_W + i * CELL_W;
                    const cellY = LABEL_ROW_H + j * CELL_H;
                    const coverage = cellMap.get(`${kp.kpId}|${plan.planId}`) ?? 0;
                    return (
                      <rect
                        key={`${kp.kpId}-${plan.planId}`}
                        x={cellX + 1}
                        y={cellY + 1}
                        width={CELL_W - 2}
                        height={CELL_H - 2}
                        fill={coverageColor(coverage)}
                        stroke="var(--color-rule)"
                        strokeWidth={0.5}
                        onMouseEnter={() =>
                          setTooltip({
                            kpName: kp.name,
                            planName: plan.title,
                            coverage,
                            x: cellX + CELL_W,
                            y: cellY,
                          })
                        }
                        onMouseLeave={() => setTooltip(null)}
                        className="cursor-pointer"
                      >
                        <title>{`${kp.name} × ${plan.title}：${coverage} 课案`}</title>
                      </rect>
                    );
                  }),
                )}
              </g>

              {/* 单元格内覆盖数文字（仅 coverage > 0 显示） */}
              <g pointerEvents="none">
                {heatmap.knowledgePoints.map((kp, i) =>
                  heatmap.lessonPlans.map((plan, j) => {
                    const coverage = cellMap.get(`${kp.kpId}|${plan.planId}`) ?? 0;
                    if (coverage === 0) return null;
                    const cellX = LABEL_COL_W + i * CELL_W + CELL_W / 2;
                    const cellY = LABEL_ROW_H + j * CELL_H + CELL_H / 2 + 4;
                    return (
                      <text
                        key={`text-${kp.kpId}-${plan.planId}`}
                        x={cellX}
                        y={cellY}
                        textAnchor="middle"
                        fontSize="10"
                        fontFamily="var(--font-family-mono)"
                        fill={textColor(coverage)}
                      >
                        {coverage}
                      </text>
                    );
                  }),
                )}
              </g>
            </svg>

            {/* Tooltip（hover 显示） */}
            {tooltip && (
              <div
                className="absolute pointer-events-none p-2 border border-rule rounded-card bg-paper text-tiny"
                style={{
                  left: `${tooltip.x + 8}px`,
                  top: `${tooltip.y + 8}px`,
                  zIndex: 10,
                }}
              >
                <p className="font-serif text-ink">{tooltip.kpName}</p>
                <p className="text-ink-muted">{tooltip.planName}</p>
                <p className="mt-1 text-accent">
                  覆盖：{tooltip.coverage} 课案
                </p>
              </div>
            )}
          </div>

          {/* 统计摘要 */}
          <div className="mt-6 grid grid-cols-3 gap-4">
            <StatCard
              label="知识点数"
              value={heatmap.knowledgePoints.length}
            />
            <StatCard
              label="课案数"
              value={heatmap.lessonPlans.length}
            />
            <StatCard
              label="总覆盖数"
              value={heatmap.cells.reduce((acc, c) => acc + c.coverage, 0)}
            />
          </div>
        </section>
      )}
    </div>
  );
}

/** 统计卡片子组件 */
function StatCard({
  label,
  value,
}: {
  label: string;
  value: number;
}): React.ReactNode {
  return (
    <div className="p-4 border border-rule rounded-card bg-surface">
      <p className="text-tiny uppercase tracking-wide text-ink-muted">
        {label}
      </p>
      <p className="mt-2 text-2xl font-serif text-ink">{value}</p>
    </div>
  );
}
