import Taro from '@tarojs/taro';
import { DEFAULT_LATITUDE, DEFAULT_LONGITUDE } from '../../../../robotaxi/constants/map';
import {
  HOME_START_SITE_SOURCE_MANUAL_SELECTED,
  writeHomeStartSiteDisplayState
} from '../../../../robotaxi/hooks/use-home-start-site-display';

type Deps = {
  mapState: any;
  siteState: any;
  toOrigin: () => void;
  getMarkerCommitDelayMs?: () => number;
  onRegionBegin?: () => void;
  onRegionSettled?: (payload: { lat: number; lon: number; isInside: boolean }) => void;
  onScaleChange?: (scale: number) => void;
};

/**
 * 地图 region-change 编排：处理地图拖拽/缩放后的吸附、回填和自动归位。
 */
export default function useRegionChange({ mapState, siteState, toOrigin, getMarkerCommitDelayMs, onRegionBegin, onRegionSettled, onScaleChange }: Deps) {
  /**
   * 查询完成后提交站点 marker：命中吸附时立即提交，未吸附时避让车辆动画窗口再提交。
   */
  const commitQueriedMarkers = (newMarkers: any[], isInside: boolean, adsorbed: boolean) => {
    if (!isInside || adsorbed) {
      mapState.commitMarkers(newMarkers);
      return;
    }
    const delayMs = typeof getMarkerCommitDelayMs === 'function' ? getMarkerCommitDelayMs() : 0;
    mapState.scheduleMarkerCommit(newMarkers, delayMs);
  };

  /**
   * 将用户显式换点后的吸附结果同步为首页确认上车点。
   */
  const syncManualSelectedStartSite = (site: any) => {
    if (!site?.latitude || !site?.longitude) {
      return;
    }
    writeHomeStartSiteDisplayState(site, HOME_START_SITE_SOURCE_MANUAL_SELECTED);
  };

  /**
   * 按最终落点回传地图结算结果，保证场站围栏与吸附后的中心点一致。
   */
  const settleRegionResult = (payload: { lat: number; lon: number; isInside: boolean }) => {
    if (typeof onRegionSettled === 'function') {
      onRegionSettled(payload);
    }
  };

  /**
   * 通过中心点主动触发吸附判断。
   * @param options.allowAdsorb 是否允许吸附到最近点位，默认允许；查看运营区域等仅浏览场景需传 false 以保持视野不被吸附打断。
   */
  const queryPointerByCenter = async (lat: number, lng: number, options?: { allowAdsorb?: boolean }) => {
    const allowAdsorb = options?.allowAdsorb !== false;
    siteState.setBounce(true);
    siteState.setShowToolTip(false);
    try {
      const { isInside, newMarkers, sites } = await mapState.updateMapData(lat, lng, undefined, { commitMarkers: false });
      if (!isInside) {
        siteState.clearCachedStartSiteSelection();
        commitQueriedMarkers(newMarkers, false, false);
        settleRegionResult({ lat, lon: lng, isInside: false });
        siteState.setIsAdsorbed(false);
        if (allowAdsorb) {
          siteState.setShowToolTip(true); // 运营区外恢复气泡提示
        }
        siteState.setBounce(false);
        return;
      }
      const nearestCandidates = sites.length > 0 ? sites : newMarkers;
      const { adsorbed, marker } = allowAdsorb
        ? siteState.tryAdsorb(lat, lng, nearestCandidates)
        : { adsorbed: false, marker: null }; // 仅浏览运营区域时不吸附最近点位
      commitQueriedMarkers(newMarkers, true, adsorbed);
      const finalLat = adsorbed && marker ? marker.latitude : lat; // 最终纬度
      const finalLng = adsorbed && marker ? marker.longitude : lng; // 最终经度
      if (allowAdsorb) {
        // 仅浏览运营区域时不回写地图中心，避免 Map 组件按旧 scale 重绘导致刚展开的运营区视野被收回
        mapState.setLatitude(finalLat);
        mapState.setLongitude(finalLng);
      }
      settleRegionResult({ lat: finalLat, lon: finalLng, isInside: true });
      setTimeout(async () => {
        siteState.setBounce(false);
        if (!adsorbed) {
          await siteState.resolveAddress(lat, lng);
        }
        if (!allowAdsorb) {
          siteState.setShowToolTip(false); // 查看运营区域期间隐藏气泡，避免遮挡围栏，拖动地图后自动恢复
        }
      }, 600);
    } catch (error) {
      siteState.setBounce(false);
    }
  };

  const handleRegionEnd = (causedBy: string, wasReturningToOrigin: boolean) => {
    siteState.setBounce(true);
    const mapCtx = Taro.createMapContext('map');
    mapCtx.getScale({
      success: (res) => {
        if (res.scale <= 3 || res.scale >= 20) {
          if (!mapState.resetTimer.current) {
            mapState.setMapScale(res.scale);
            mapState.resetTimer.current = setTimeout(() => {
              toOrigin();
            }, 6000);
          }
        }
        if (typeof onScaleChange === 'function') {
          onScaleChange(res.scale);
        }
      }
    });
    mapCtx.getCenterLocation({
      success: async (res) => {
        const { latitude: lat, longitude: lng } = res;
        if (
          !lat ||
          !lng ||
          (Math.abs(lat - DEFAULT_LATITUDE) < 0.0001 && Math.abs(lng - DEFAULT_LONGITUDE) < 0.0001)
        ) {
          siteState.setBounce(false);
          return;
        }
        
        if (causedBy === 'gesture' || causedBy === 'drag' || causedBy === 'scale' || wasReturningToOrigin) {
          // 只有发生显著位移时才同步经纬度，避免微小抖动引发的二次重绘
          if (Math.abs(mapState.latitude - lat) > 0.0001 || Math.abs(mapState.longitude - lng) > 0.0001) {
            mapState.setLatitude(lat);
            mapState.setLongitude(lng);
          }
        }

        try {
          const { isInside, newMarkers, sites } = await mapState.updateMapData(lat, lng, undefined, { commitMarkers: false });
          if (!isInside) {
            siteState.clearCachedStartSiteSelection();
            commitQueriedMarkers(newMarkers, false, false);
            settleRegionResult({ lat, lon: lng, isInside: false });
            siteState.setIsAdsorbed(false);
            siteState.setShowToolTip(true); // 运营区外恢复气泡提示
            siteState.setBounce(false);
            return;
          }
          const nearestCandidates = sites.length > 0 ? sites : newMarkers;
          const { adsorbed, marker } = siteState.tryAdsorb(lat, lng, nearestCandidates);
          commitQueriedMarkers(newMarkers, true, adsorbed);
          const finalLat = adsorbed && marker ? marker.latitude : lat; // 最终纬度
          const finalLng = adsorbed && marker ? marker.longitude : lng; // 最终经度
          if (adsorbed && marker && (causedBy === 'gesture' || causedBy === 'drag' || wasReturningToOrigin)) {
            syncManualSelectedStartSite(marker);
          }
          settleRegionResult({ lat: finalLat, lon: finalLng, isInside: true });
          if ((causedBy === 'gesture' || causedBy === 'drag' || wasReturningToOrigin) && marker) {
            mapCtx.moveToLocation({
              latitude: marker.latitude,
              longitude: marker.longitude
            });
            mapState.setLatitude(marker.latitude);
            mapState.setLongitude(marker.longitude);
          }
          setTimeout(async () => {
            siteState.setBounce(false);
            if (!adsorbed) {
              await siteState.resolveAddress(lat, lng);
            }
          }, 600);
        } catch (error) {
          siteState.setBounce(false);
        }
      }
    });
  };

  /**
   * region-change 事件入口。
   */
  const handleRegionChange = (e: any) => {
    const type = e?.type || e?.detail?.type;
    const causedBy = e?.causedBy || e?.detail?.causedBy;
    if (mapState.isLocationAuthDenied) return;
    if (causedBy === 'gesture' || causedBy === 'drag' || causedBy === 'scale') {
      mapState.shouldIgnoreRegionChange.current = false;
      if (mapState.resetTimer.current) {
        clearTimeout(mapState.resetTimer.current);
        mapState.resetTimer.current = null;
      }
    } else if (mapState.isReturningToOrigin.current) {
      mapState.shouldIgnoreRegionChange.current = false;
    } else {
      mapState.shouldIgnoreRegionChange.current = true;
      return;
    }
    if (type === 'begin') {
      siteState.setShowToolTip(false);
      if (typeof onRegionBegin === 'function') {
        onRegionBegin();
      }
      return;
    }
    if (type !== 'end') return;
    const wasReturningToOrigin = mapState.isReturningToOrigin.current;
    if (mapState.isReturningToOrigin.current) {
      mapState.isReturningToOrigin.current = false;
    }
    if (mapState.shouldIgnoreRegionChange.current) {
      mapState.shouldIgnoreRegionChange.current = false;
      return;
    }
    handleRegionEnd(causedBy, wasReturningToOrigin);
  };

  return { handleRegionChange, queryPointerByCenter };
}
