import { useI18n } from '@/lib/i18n';

// The sky, seen from underneath it.
//
// The map answers "where is the satellite over the earth". This answers "where
// do I look", which during a pass is the question that matters: whether the
// bird comes over the top or clips the horizon behind the house is something no
// amount of azimuth and elevation digits conveys, and one glance at a polar
// plot settles it.
//
// The projection is the one every satellite tracker uses and every operator
// already reads: the centre is the zenith, the outer circle is the horizon, and
// north is up. So the radius is (90 − elevation), NOT the elevation — a
// satellite overhead is a dot in the middle, and a pass that stays near the rim
// is one that never rises.

export type SkyPoint = { at: string; az: number; el: number };

export function SkyPlot({ track, az, el, name, visible, size = 300 }: {
  // The pass, sampled from rise to set. Empty draws the dial alone, which is
  // still worth showing: it says where the antenna is pointing now.
  track: SkyPoint[];
  // Where the satellite is at this instant, or null when it is not up.
  az?: number | null;
  el?: number | null;
  name?: string;
  visible?: boolean;
  size?: number;
}) {
  const { t } = useI18n();
  const R = size / 2 - 14;      // the horizon circle
  const cx = size / 2, cy = size / 2;

  // Where a bearing and an elevation land on the dial.
  const pt = (azDeg: number, elDeg: number): [number, number] => {
    const r = R * (90 - Math.max(0, Math.min(90, elDeg))) / 90;
    const a = (azDeg * Math.PI) / 180;
    return [cx + r * Math.sin(a), cy - r * Math.cos(a)];
  };

  const rings = [15, 30, 45, 60, 75];
  const path = track.length > 1
    ? track.map((p, i) => `${i === 0 ? 'M' : 'L'}${pt(p.az, p.el).map((v) => v.toFixed(1)).join(' ')}`).join(' ')
    : '';

  // Ticks every 10°, longer every 30°, so the rim reads as a compass rather
  // than a plain circle.
  const ticks = [];
  for (let a = 0; a < 360; a += 10) {
    const long = a % 30 === 0;
    const rad = (a * Math.PI) / 180;
    const r1 = R, r2 = R - (long ? 7 : 4);
    ticks.push(
      <line key={a}
        x1={cx + r1 * Math.sin(rad)} y1={cy - r1 * Math.cos(rad)}
        x2={cx + r2 * Math.sin(rad)} y2={cy - r2 * Math.cos(rad)}
        stroke="var(--border)" strokeWidth={long ? 1.4 : 0.8} />,
    );
  }

  const here = az != null && el != null ? pt(az, el) : null;
  const start = track.length > 1 ? pt(track[0].az, track[0].el) : null;
  const end = track.length > 1 ? pt(track[track.length - 1].az, track[track.length - 1].el) : null;

  return (
    <svg viewBox={`0 0 ${size} ${size}`} className="w-full h-auto select-none" role="img"
      aria-label={t('sat.skyPlot')}>
      <defs>
        {/* An arrowhead on the track: a pass has a direction, and which way the
            satellite is travelling decides where to point the antenna next. */}
        <marker id="skyArrow" viewBox="0 0 10 10" refX="6" refY="5"
          markerWidth="5" markerHeight="5" orient="auto-start-reverse">
          <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--success)" />
        </marker>
      </defs>

      <circle cx={cx} cy={cy} r={R} fill="var(--muted)" fillOpacity={0.25}
        stroke="var(--border)" strokeWidth={1.5} />
      {rings.map((e) => (
        <circle key={e} cx={cx} cy={cy} r={R * (90 - e) / 90}
          fill="none" stroke="var(--border)" strokeWidth={0.6} strokeDasharray="3 4" />
      ))}
      {ticks}

      {/* The cardinal cross. */}
      <line x1={cx} y1={cy - R} x2={cx} y2={cy + R} stroke="var(--border)" strokeWidth={0.6} />
      <line x1={cx - R} y1={cy} x2={cx + R} y2={cy} stroke="var(--border)" strokeWidth={0.6} />

      {([
        { lbl: 'N', x: cx, y: cy - R - 3, anchor: 'middle' },
        { lbl: 'S', x: cx, y: cy + R + 11, anchor: 'middle' },
        { lbl: 'E', x: cx + R + 4, y: cy + 4, anchor: 'start' },
        { lbl: 'W', x: cx - R - 4, y: cy + 4, anchor: 'end' },
      ] as const).map((c) => (
        <text key={c.lbl} x={c.x} y={c.y} textAnchor={c.anchor}
          fontSize={11} fontWeight={600} fill="var(--muted-foreground)">{c.lbl}</text>
      ))}

      {/* Elevation labels along the west arm, the way a tracker draws them. */}
      {[0, 30, 60].map((e) => (
        <text key={e} x={cx - R * (90 - e) / 90 + 2} y={cy + 10} fontSize={8}
          fill="var(--muted-foreground)" opacity={0.8}>{e}°</text>
      ))}

      {/* The pass. */}
      {path && (
        <path d={path} fill="none" stroke="var(--success)" strokeWidth={1.6}
          strokeDasharray="5 3" markerMid="url(#skyArrow)" markerEnd="url(#skyArrow)"
          opacity={0.85} />
      )}
      {start && <circle cx={start[0]} cy={start[1]} r={3} fill="none" stroke="var(--success)" strokeWidth={1.4} />}
      {end && <circle cx={end[0]} cy={end[1]} r={3} fill="var(--success)" opacity={0.6} />}

      {/* Where it is now. Hollow and grey below the horizon: the numbers are
          still right, but nothing can be worked through the earth. */}
      {here && (
        <g>
          <line x1={here[0] - 6} y1={here[1]} x2={here[0] + 6} y2={here[1]}
            stroke={visible ? 'var(--success)' : 'var(--muted-foreground)'} strokeWidth={1.4} />
          <line x1={here[0]} y1={here[1] - 6} x2={here[0]} y2={here[1] + 6}
            stroke={visible ? 'var(--success)' : 'var(--muted-foreground)'} strokeWidth={1.4} />
          <circle cx={here[0]} cy={here[1]} r={4}
            fill={visible ? 'var(--success)' : 'none'}
            stroke={visible ? 'var(--background)' : 'var(--muted-foreground)'} strokeWidth={1.2} />
        </g>
      )}

      {/* The name and the look angles, in the middle, where a tracker puts them
          — big enough to read from the other side of the shack. */}
      {!!name && (
        <text x={cx} y={cy - R * 0.42} textAnchor="middle" fontSize={18} fontWeight={600}
          fill="var(--foreground)" opacity={0.85}>{name}</text>
      )}
      {az != null && el != null && (
        <text x={cx} y={cy - R * 0.22} textAnchor="middle" fontSize={12}
          fill="var(--muted-foreground)" className="tabular-nums">
          AZ {az.toFixed(1)}°  EL {el.toFixed(1)}°
        </text>
      )}
    </svg>
  );
}
