const PICTOGRAM_BASE = "assets/pictograms";

const V3Pictograms = {
  mascot: {
    ready: `${PICTOGRAM_BASE}/mascot-ready.png`,
    think: `${PICTOGRAM_BASE}/mascot-think.png`,
    safe: `${PICTOGRAM_BASE}/mascot-safe.png`,
    point: `${PICTOGRAM_BASE}/mascot-point.png`,
    listen: `${PICTOGRAM_BASE}/mascot-listen.png`,
    mark: `${PICTOGRAM_BASE}/mascot-mark.png`,
    compare: `${PICTOGRAM_BASE}/mascot-compare.png`,
    present: `${PICTOGRAM_BASE}/mascot-present.png`,
  },
  object: {
    sun: `${PICTOGRAM_BASE}/icon-sun.png`,
    satellite: `${PICTOGRAM_BASE}/icon-satellite.png`,
    dish: `${PICTOGRAM_BASE}/icon-dish.png`,
    signal: `${PICTOGRAM_BASE}/icon-signal.png`,
    evidence: `${PICTOGRAM_BASE}/icon-evidence.png`,
  },
};

function resolvePictogram(asset) {
  if (!asset) return V3Pictograms.object.signal;
  if (asset.includes("/")) return asset;
  return V3Pictograms.mascot[asset] || V3Pictograms.object[asset] || V3Pictograms.object.signal;
}

function MascotPose({ pose = "ready", className = "" }) {
  return (
    <img
      className={`mascot-pose ${className}`}
      src={V3Pictograms.mascot[pose] || V3Pictograms.mascot.ready}
      alt=""
      aria-hidden="true"
    />
  );
}

function TargetBadge({ scenario, compact = false }) {
  return (
    <div className={`target-badge ${compact ? "compact" : ""}`} data-scenario={scenario.kind}>
      <img src={scenario.targetAsset} alt="" aria-hidden="true" />
      <span>
        <small>这次看</small>
        <strong>{scenario.targetName}</strong>
      </span>
    </div>
  );
}

function VisualInstruction({
  scenario,
  instruction,
  ageBand,
  className = "",
  hero = null,
}) {
  const steps = instruction.steps || [];
  return (
    <section
      className={`visual-instruction ${className}`}
      aria-label={`${instruction.verb}。${instruction.cue || ""}`}
      data-scenario={scenario.kind}
    >
      <div
        className={`visual-hero-art ${hero ? "has-custom-hero" : ""}`}
        aria-hidden={hero ? undefined : "true"}
      >
        {hero || (
          <React.Fragment>
            <span className="target-orbit-line"></span>
            <MascotPose pose={instruction.pose} />
            <img className="visual-target-art" src={scenario.targetAsset} alt="" />
          </React.Fragment>
        )}
      </div>
      <div className="visual-instruction-copy">
        <span>现在要做</span>
        <strong>{instruction.verb}</strong>
        {ageBand === "9-12" && instruction.cue ? <p>{instruction.cue}</p> : null}
      </div>
      {steps.length ? (
        <div className="instruction-step-strip" aria-label="看图步骤">
          {steps.map((step, index) => (
            <div className="instruction-step" key={`${step.label}-${index}`}>
              <img src={resolvePictogram(step.asset)} alt="" aria-hidden="true" />
              <strong>{step.label}</strong>
            </div>
          ))}
        </div>
      ) : null}
    </section>
  );
}

const PICTURE_PATTERNS = Object.freeze({
  rise: [24, 42, 68, 92],
  flat: [54, 56, 53, 55],
  fall: [92, 68, 42, 24],
  bell: [22, 48, 92, 48, 22],
  leftHigh: [88, 72, 38, 30],
  rightHigh: [30, 38, 72, 88],
  same: [52, 54, 52, 54],
  uncertain: [36, 74, 44, 68],
  doppler: [86, 68, 50, 32, 18],
  wideBlock: [18, 20, 72, 76, 73, 20],
  pulse: [18, 20, 96, 20, 18],
});

function PictureChoiceArt({ kind = "rise" }) {
  const bars = PICTURE_PATTERNS[kind] || PICTURE_PATTERNS.rise;
  return (
    <span className={`picture-choice-art ${kind}`} aria-hidden="true">
      <span className="picture-bars">
        {bars.map((height, index) => <i key={index} style={{ "--bar-height": `${height}%` }}></i>)}
      </span>
    </span>
  );
}

function PredictionMeaningAnimation({ scenario, option }) {
  const kind = option && option.art ? option.art : "waiting";
  const bars = PICTURE_PATTERNS[kind] || [32, 58, 42, 70, 48];
  const label = option
    ? `${option.label}。${option.help || ""}`
    : "点选下面的图卡，看看它代表怎样的变化";
  return (
    <div
      className="prediction-meaning-animation"
      data-kind={kind}
      role="img"
      aria-label={label}
      key={option ? option.value : "waiting"}
    >
      <div className="meaning-animation-head">
        <span>{option ? "这张图卡表示" : "先选一张图卡"}</span>
        <strong>{option ? option.label : "变化会在这里动起来"}</strong>
      </div>
      <div className="meaning-signal-stage">
        <span className="meaning-baseline"></span>
        <span className="meaning-scan-beam"></span>
        <div className="meaning-bars">
          {bars.map((height, index) => (
            <i
              key={`${kind}-${index}`}
              style={{
                "--meaning-height": `${height}%`,
                "--meaning-delay": `${index * 90}ms`,
              }}
            ></i>
          ))}
        </div>
        <img src={scenario.targetAsset} alt="" aria-hidden="true" />
      </div>
      <small>{option ? option.help : "选好之前，不会提前告诉答案"}</small>
    </div>
  );
}

function clampPointing(value, min, max) {
  return Math.max(min, Math.min(max, Number(value) || 0));
}

function skyPosition(azimuth, elevation) {
  const radius = (90 - clampPointing(elevation, 0, 90)) / 90 * 42;
  const angle = (Number(azimuth) - 90) * Math.PI / 180;
  return {
    x: 50 + Math.cos(angle) * radius,
    y: 50 + Math.sin(angle) * radius,
  };
}

function simulatedPointing(scenario, progress) {
  const ratio = clampPointing(progress, 0, 100) / 100;
  if (scenario.kind === "satellite_pass") {
    const targetAzimuth = 62 + ratio * 76;
    const targetElevation = 15 + ratio * 45;
    return {
      azimuth: targetAzimuth - (1 - ratio) * 36,
      elevation: targetElevation - (1 - ratio) * 12,
      targetAzimuth,
      targetElevation,
      sourceLabel: "教学模拟遥测",
    };
  }
  const targetAzimuth = 228;
  const targetElevation = 47;
  return {
    azimuth: 126 + ratio * (targetAzimuth - 126),
    elevation: 11 + ratio * (targetElevation - 11),
    targetAzimuth,
    targetElevation,
    sourceLabel: "教学模拟遥测",
  };
}

function AntennaPointingVisual({ scenario, progress, telemetry = null }) {
  const simulated = simulatedPointing(scenario, progress);
  const current = telemetry && Number.isFinite(Number(telemetry.azimuth)) &&
      Number.isFinite(Number(telemetry.elevation))
    ? {
      ...simulated,
      ...telemetry,
      azimuth: Number(telemetry.azimuth),
      elevation: Number(telemetry.elevation),
      targetAzimuth: Number.isFinite(Number(telemetry.targetAzimuth))
        ? Number(telemetry.targetAzimuth)
        : simulated.targetAzimuth,
      targetElevation: Number.isFinite(Number(telemetry.targetElevation))
        ? Number(telemetry.targetElevation)
        : simulated.targetElevation,
      sourceLabel: telemetry.sourceLabel || "现场遥测",
    }
    : simulated;
  const target = skyPosition(current.targetAzimuth, current.targetElevation);
  const pointing = skyPosition(current.azimuth, current.elevation);
  const error = Math.hypot(
    current.targetAzimuth - current.azimuth,
    current.targetElevation - current.elevation,
  );
  return (
    <div
      className="antenna-pointing-visual"
      role="img"
      aria-label={`天线当前方位 ${Math.round(current.azimuth)} 度，仰角 ${Math.round(current.elevation)} 度`}
      data-source={telemetry ? "onsite" : "simulation"}
    >
      <div className="pointing-live-label">
        <i aria-hidden="true"></i>
        <span>{current.sourceLabel}</span>
      </div>
      <div className="pointing-sky-dome">
        <span className="compass-north">北</span>
        <span className="compass-east">东</span>
        <span className="compass-south">南</span>
        <span className="compass-west">西</span>
        <i
          className="pointing-target-dot"
          style={{ left: `${target.x}%`, top: `${target.y}%` }}
        ></i>
        <span
          className="pointing-current-reticle"
          style={{ left: `${pointing.x}%`, top: `${pointing.y}%` }}
        >
          <img src={V3Pictograms.object.dish} alt="" aria-hidden="true" />
        </span>
      </div>
      <div className="pointing-metrics">
        <span><small>方位 AZ</small><strong>{Math.round(current.azimuth)}°</strong></span>
        <span><small>仰角 EL</small><strong>{Math.round(current.elevation)}°</strong></span>
        <span data-close={error < 4 ? "true" : "false"}>
          <small>距离目标</small>
          <strong>{error < 4 ? "已对准" : `${Math.round(error)}°`}</strong>
        </span>
      </div>
    </div>
  );
}

function EvidenceCounter({ count, max = 3 }) {
  return (
    <div className="evidence-counter" role="status" aria-label={`已经留下 ${count} 个证据标记`}>
      {Array.from({ length: max }, (_, index) => (
        <span className={index < count ? "filled" : ""} key={index} aria-hidden="true">✦</span>
      ))}
    </div>
  );
}

Object.assign(window, {
  V3Pictograms,
  resolvePictogram,
  MascotPose,
  TargetBadge,
  VisualInstruction,
  PictureChoiceArt,
  PredictionMeaningAnimation,
  AntennaPointingVisual,
  EvidenceCounter,
});
