import { BaseMap, ZoneData } from '@/pages/Slave/SGW/Map/type';
import {
  getAreaFromRadius,
  getCircleRadius,
} from '@/utils/slave/sgw/geomUtils';
import { type ProFormInstance } from '@ant-design/pro-components';
import { Feature } from 'ol';
import { MutableRefObject, useEffect, useRef } from 'react';
import type { ZoneFormData } from '../type';
import { GeometryType, ZoneFormField } from '../type';

// Default zone data for drawing features
const DEFAULT_ZONE_DATA: ZoneData = { type: 'default' };

interface DrawnFeatureData {
  type: string;
  coordinates: any;
  feature: any;
}

interface MapGeometrySyncOptions {
  baseMap: MutableRefObject<BaseMap | null>;
  dataLayerId: string;
  form: MutableRefObject<ProFormInstance<ZoneFormData> | undefined>;
  shape?: number;
  enabled?: boolean;
}

/**
 * Custom hook to sync geometry between Map and Form
 * - Draw on Map -> Update Form
 * - Modify on Map -> Update Form
 * - Form changes -> Update Map (optional)
 */
export const useMapGeometrySync = (options: MapGeometrySyncOptions) => {
  const { baseMap, dataLayerId, form, enabled = true } = options;
  const isHandlingUpdateRef = useRef(false);

  useEffect(() => {
    if (!baseMap || !enabled) return;

    // Handle feature drawn event
    const handleFeatureDrawn = (data: DrawnFeatureData) => {
      if (isHandlingUpdateRef.current) return;
      isHandlingUpdateRef.current = true;

      switch (data.type) {
        case 'Polygon': {
          const currentGeometry =
            form.current?.getFieldValue(ZoneFormField.PolygonGeometry) || [];
          const polygonId = `polygon_${Date.now()}`; // Tạo unique ID
          data.feature.set('polygonId', polygonId); // Sửa: set trực tiếp key-value
          const polygonCoords = data.coordinates;
          form.current?.setFieldsValue({
            [ZoneFormField.PolygonGeometry]: [
              ...currentGeometry,
              {
                geometry: polygonCoords[0],
                id: polygonId,
              },
            ],
          });
          break;
        }

        case 'LineString': {
          baseMap.current?.clearFeatures(dataLayerId);
          const lineCoords = data.coordinates;
          form.current?.setFieldsValue({
            [ZoneFormField.PolylineData]: JSON.stringify(lineCoords),
          });
          break;
        }

        case 'Circle': {
          baseMap.current?.clearFeatures(dataLayerId);
          const circleData = data.coordinates;
          console.log('Circle Data: ', circleData);
          form.current?.setFieldsValue({
            [ZoneFormField.CircleData]: {
              center: circleData.center,
              area: getAreaFromRadius(circleData.radius),
            },
          });
          break;
        }

        case 'Point':
          // Point is stored as circle with small radius
          // form?.setFieldsValue({
          //   [ZoneFormField.CircleData]: {
          //     center: data.coordinates,
          //     radius: 100, // Default radius for point
          //   },
          //   [ZoneFormField.Radius]: 100,
          // });
          break;
      }

      setTimeout(() => {
        isHandlingUpdateRef.current = false;
      }, 100);
    };

    // Handle feature modified event
    const handleFeatureModified = (data: {
      feature: any;
      coordinates: any;
    }) => {
      if (isHandlingUpdateRef.current) return;
      isHandlingUpdateRef.current = true;

      const geometry = data.feature.getGeometry();
      if (!geometry) {
        isHandlingUpdateRef.current = false;
        return;
      }

      const geomType = geometry.getType();

      switch (geomType) {
        case 'Polygon': {
          const polygonId = data.feature.get('polygonId');

          if (polygonId) {
            const currentGeometry =
              form.current?.getFieldValue(ZoneFormField.PolygonGeometry) || [];
            const modifiedCoords = data.coordinates[0];
            const updatedGeometry = currentGeometry.map((item: any) =>
              item.id === polygonId
                ? { ...item, geometry: modifiedCoords }
                : item,
            );

            form.current?.setFieldsValue({
              [ZoneFormField.PolygonGeometry]: updatedGeometry,
            });
          }
          break;
        }
        case 'LineString': {
          form.current?.setFieldsValue({
            [ZoneFormField.PolylineData]: JSON.stringify(data.coordinates),
          });
          break;
        }

        case 'Circle': {
          form.current?.setFieldsValue({
            [ZoneFormField.CircleData]: {
              center: data.coordinates.center,
              // radius: data.coordinates.radius,
              area: getAreaFromRadius(data.coordinates.radius),
            },
          });
          break;
        }
      }

      setTimeout(() => {
        isHandlingUpdateRef.current = false;
      }, 100);
    };

    // Register event listeners
    baseMap.current?.onFeatureDrawn(handleFeatureDrawn);
    baseMap.current?.onFeatureModified(handleFeatureModified);

    // Cleanup
    return () => {
      // Note: BaseMap doesn't have off method, so events will remain
      // This is acceptable as the component unmounts
    };
  }, [baseMap, enabled]);

  /**
   * Update map display based on current form data
   */
  const updateMapFromForm = (type: GeometryType) => {
    if (!baseMap || !form) return;
    const formCurrent = form.current;
    let geometryData;
    if (type === GeometryType.POLYGON) {
      geometryData =
        formCurrent?.getFieldValue(ZoneFormField.PolygonGeometry) || [];
    } else if (type === GeometryType.LINESTRING) {
      const polylineString =
        formCurrent?.getFieldValue(ZoneFormField.PolylineData) || [];
      geometryData = JSON.parse(polylineString);
    } else if (type === GeometryType.CIRCLE) {
      geometryData = formCurrent?.getFieldValue(ZoneFormField.CircleData)
        ? [formCurrent?.getFieldValue(ZoneFormField.CircleData)]
        : [];
    }

    if (!geometryData || geometryData.length === 0) {
      baseMap.current?.clearFeatures(dataLayerId);
      return;
    }

    // Nếu đang xử lý event từ Map (vẽ/sửa), KHÔNG clear và vẽ lại
    // vì Draw interaction đã add feature vào map sẵn rồi
    if (isHandlingUpdateRef.current) {
      return;
    }

    // Clear existing features trước khi vẽ lại (chỉ khi không đang handle map event)
    baseMap.current?.clearFeatures(dataLayerId);

    switch (type) {
      case GeometryType.POLYGON:
        {
          const features: Feature[] = [];
          geometryData.forEach((geom: any) => {
            const feature = baseMap.current?.addPolygon(
              dataLayerId,
              [geom.geometry],
              DEFAULT_ZONE_DATA,
              geom.id,
            );
            features.push(feature!);
          });
          baseMap.current?.zoomToFeatures(features);
        }
        break;
      case GeometryType.LINESTRING:
        {
          const feature = baseMap.current?.addPolyline(
            dataLayerId,
            geometryData,
            DEFAULT_ZONE_DATA,
          );
          baseMap.current?.zoomToFeatures([feature!]);
        }
        break;
      case GeometryType.CIRCLE:
        {
          const feature = baseMap.current?.addCircle(
            dataLayerId,
            geometryData[0].center,
            getCircleRadius(geometryData[0].area),
            DEFAULT_ZONE_DATA,
          );
          baseMap.current?.zoomToFeatures([feature!]);
        }
        break;
    }
  };

  /**
   * Clear all drawn features from map
   */
  const clearMapFeatures = () => {
    if (!baseMap) return;
    baseMap.current?.clearFeatures(dataLayerId);
  };

  /**
   * Draw existing geometry on map (for update mode)
   */
  const drawExistingGeometry = (geometry: any) => {
    if (!baseMap || !geometry) return;

    clearMapFeatures();

    if (geometry.geom_type === GeometryType.POLYGON && geometry.polygons) {
      geometry.polygons.forEach((polygonCoords: number[][]) => {
        baseMap.current?.addPolygon(
          dataLayerId,
          [polygonCoords],
          DEFAULT_ZONE_DATA,
        );
      });
    } else if (
      geometry.geom_type === GeometryType.LINESTRING &&
      geometry.coordinates
    ) {
      baseMap.current?.addPolyline(
        dataLayerId,
        geometry.coordinates,
        DEFAULT_ZONE_DATA,
      );
    } else if (
      geometry.geom_type === GeometryType.CIRCLE &&
      geometry.center &&
      geometry.radius
    ) {
      baseMap.current?.addCircle(
        dataLayerId,
        geometry.center,
        geometry.radius,
        DEFAULT_ZONE_DATA,
      );
    }
  };

  return {
    updateMapFromForm,
    clearMapFeatures,
    drawExistingGeometry,
  };
};

export default useMapGeometrySync;
