import { DEG2RAD, RAD2DEG, EARTH_RADIUS_M } from '../constants';

export const clampNumber = (value: number, minValue: number, maxValue: number) =>
  Math.max(minValue, Math.min(maxValue, value));

export function wrapLonDeg(lon: number) {
  const v = ((lon + 180) % 360 + 360) % 360;
  return v - 180;
}

export function destinationPointLngLat(
  from: [number, number],
  bearingDeg: number,
  distanceMeters: number,
): [number, number] {
  const [lonDeg, latDeg] = from;
  const lat1 = latDeg * DEG2RAD;
  const lon1 = lonDeg * DEG2RAD;
  const brng = bearingDeg * DEG2RAD;
  const dr = Math.max(0, distanceMeters) / EARTH_RADIUS_M;
  if (!Number.isFinite(dr) || dr === 0) return [lonDeg, latDeg];

  const sinLat1 = Math.sin(lat1);
  const cosLat1 = Math.cos(lat1);
  const sinDr = Math.sin(dr);
  const cosDr = Math.cos(dr);

  const lat2 = Math.asin(sinLat1 * cosDr + cosLat1 * sinDr * Math.cos(brng));
  const lon2 =
    lon1 +
    Math.atan2(
      Math.sin(brng) * sinDr * cosLat1,
      cosDr - sinLat1 * Math.sin(lat2),
    );

  const outLon = wrapLonDeg(lon2 * RAD2DEG);
  const outLat = clampNumber(lat2 * RAD2DEG, -85.0, 85.0);
  return [outLon, outLat];
}

export function circleRingLngLat(center: [number, number], radiusMeters: number, steps = 36): [number, number][] {
  // 반경이 지구 둘레의 1/4 (≈10,000km)을 넘으면 클램핑
  const r = clampNumber(radiusMeters, 0, EARTH_RADIUS_M * Math.PI * 0.5);

  const ring: [number, number][] = [];
  for (let i = 0; i <= steps; i++) {
    const a = (i / steps) * Math.PI * 2;
    const pt = destinationPointLngLat(center, a * RAD2DEG, r);
    ring.push(pt);
  }
  // 고리 닫기 보정
  if (ring.length > 1) {
    ring[ring.length - 1] = ring[0];
  }
  return ring;
}

export function normalizeAngleDeg(value: number, offset = 0): number {
  const v = value + offset;
  return ((v % 360) + 360) % 360;
}
