import { afterEach, expect, test, vi } from 'vitest';
import {
  buildAMapMarkerURL,
  gcj02ToWgs84,
  isValidAMapCoordinate,
  loadAMap,
  type AMapLike,
  wgs84ToGcj02
} from './amap';

afterEach(() => {
  delete window.__LINGNIU_APP_CONFIG__;
  delete window.AMapLoader;
  document.querySelector('script[src="https://webapi.amap.com/loader.js"]')?.remove();
});

test('accepts coordinates inside the China vehicle service range', () => {
  expect(isValidAMapCoordinate(116.397128, 39.916527)).toBe(true);
  expect(isValidAMapCoordinate(87.6379, 43.98146)).toBe(true);
});

test('rejects placeholder and out-of-range coordinates', () => {
  expect(isValidAMapCoordinate(0, 0)).toBe(false);
  expect(isValidAMapCoordinate(-0.999999, -0.999999)).toBe(false);
  expect(isValidAMapCoordinate(139.6917, 35.6895)).toBe(false);
  expect(isValidAMapCoordinate(121.4737, 10)).toBe(false);
});

test('converts WGS-84 coordinates to GCJ-02 and supports a precise viewport round trip', () => {
  const wgs: [number, number] = [116.397128, 39.916527];
  const gcj = wgs84ToGcj02(...wgs);
  expect(gcj[0]).toBeCloseTo(116.40337, 5);
  expect(gcj[1]).toBeCloseTo(39.91793, 5);
  const roundTrip = gcj02ToWgs84(...gcj);
  expect(roundTrip[0]).toBeCloseTo(wgs[0], 6);
  expect(roundTrip[1]).toBeCloseTo(wgs[1], 6);
});

test('keeps coordinates outside China unchanged and converts AMap marker links at the rendering boundary', () => {
  expect(wgs84ToGcj02(2.3522, 48.8566)).toEqual([2.3522, 48.8566]);
  const url = new URL(buildAMapMarkerURL({ longitude: 116.397128, latitude: 39.916527, name: '测试车辆' }));
  const position = url.searchParams.get('position')?.split(',').map(Number) ?? [];
  expect(position[0]).toBeCloseTo(116.40337, 5);
  expect(position[1]).toBeCloseTo(39.91793, 5);
});

test('retries the SDK load after a transient AMap loader rejection', async () => {
  const amap = {} as AMapLike;
  const load = vi.fn()
    .mockRejectedValueOnce(new Error('temporary network failure'))
    .mockResolvedValueOnce(amap);
  window.__LINGNIU_APP_CONFIG__ = { amapWebJsKey: 'amap-web-key' };
  window.AMapLoader = { load };

  await expect(loadAMap(['AMap.Geocoder'])).rejects.toThrow('temporary network failure');
  await expect(loadAMap(['AMap.Geocoder'])).resolves.toBe(amap);
  expect(load).toHaveBeenCalledTimes(2);
});

test('removes a failed loader script so a later request can recover', async () => {
  const amap = {} as AMapLike;
  window.__LINGNIU_APP_CONFIG__ = { amapWebJsKey: 'amap-web-key' };

  const firstAttempt = loadAMap(['AMap.ToolBar']);
  const failedScript = document.querySelector<HTMLScriptElement>('script[src="https://webapi.amap.com/loader.js"]');
  expect(failedScript).not.toBeNull();
  failedScript?.dispatchEvent(new Event('error'));
  await expect(firstAttempt).rejects.toThrow('高德地图 Loader 加载失败');
  expect(document.querySelector('script[src="https://webapi.amap.com/loader.js"]')).toBeNull();

  window.AMapLoader = { load: vi.fn().mockResolvedValue(amap) };
  await expect(loadAMap(['AMap.ToolBar'])).resolves.toBe(amap);
});
