import { getBadgeStatus } from '@/components/shared/ThingShared';
import { DURATION_POLLING_PRESENTATIONS } from '@/constants';
import useGetShipSos from '@/models/slave/sgw/useShipSos';
import { apiSearchThings } from '@/services/master/ThingController';
import { formatUnixTime } from '@/utils/slave/sgw/timeUtils';
import { DownOutlined, FilterOutlined, UpOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { ParamsType, useToken } from '@ant-design/pro-components';
import ProTable from '@ant-design/pro-table';
import { useIntl } from '@umijs/max';
import {
  Button,
  Drawer,
  Flex,
  message,
  notification,
  Tag,
  Tooltip,
  Typography,
} from 'antd';
import { Feature } from 'ol';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { useCallback, useEffect, useRef, useState } from 'react';
import TagState from '../../../../components/shared/TagState';
import { BaseMap } from './components/BaseMap';
import MultipleShips from './components/MultipleShips';
import ShipDetail, { ShipDetailMessageAction } from './components/ShipDetail';
import ShipSearchForm, {
  SearchShipResponse,
} from './components/ShipSearchForm';
import { renderSosOverlay } from './components/SosOverlay';
import VietNamMap, { VietNamMapRef } from './components/VietNamMap';
import { getShipNameColor } from './config/MapConfig';
import styles from './index.less';
import {
  DATA_LAYER,
  GPSParseResult,
  TagStateCallbackPayload,
  TEMPORARY_LAYER,
} from './type';

const MapPage = () => {
  // Create a ref for VietNamMap to access BaseMap methods
  const vietNamMapRef = useRef<VietNamMapRef>(null);
  const baseMap = useRef<BaseMap | null>(null);
  // Lưu các cancel functions của sosPulse để cleanup
  const sosPulseCancelRefs = useRef<(() => void)[]>([]);
  // Lưu các cleanup functions của overlay để cleanup
  const overlayCleanupRefs = useRef<Map<string, () => void>>(new Map());
  const [stateQuery, setStateQuery] = useState<
    TagStateCallbackPayload | undefined
  >(undefined);
  const token = useToken();
  const intl = useIntl();
  const [things, setThings] = useState<SgwModel.SgwThingsResponse | null>(null);
  const [isCollapsed, setIsCollapsed] = useState<boolean>(true);
  const tableRef = useRef<ActionType>();
  const [notificationApi, contextHolder] = notification.useNotification();
  const [messageApi, messageContextHolder] = message.useMessage();
  const [showMultiShipsDrawer, setShowMultiShipsDrawer] =
    useState<boolean>(false);
  const [multipleThingsSelected, setMultipleThingsSelected] = useState<
    SgwModel.SgwThing[]
  >([]);
  const [formSearchData, setFormSearchData] =
    useState<SearchShipResponse | null>(null);
  const [openFormSearch, setOpenFormSearch] = useState(false);
  const { shipSos, getShipSosWs } = useGetShipSos();

  const handleClickOneThing = (thing: SgwModel.SgwThing) => {
    if (baseMap.current === null) {
      console.log('BaseMap is not ready yet');
      return;
    }
    notificationApi.open({
      message: (
        <Flex justify="center">
          <Typography.Title level={4}>{`${intl.formatMessage({
            id: 'map.ship_detail.name',
            defaultMessage: 'Device Information',
          })} ${thing.name}`}</Typography.Title>
        </Flex>
      ),
      key: `ship-detail-${thing.id}`,
      description: baseMap && (
        <ShipDetail
          thing={thing}
          messageApi={messageApi}
          mapController={baseMap.current}
        />
      ),
      placement: 'bottomRight',
      actions: <ShipDetailMessageAction />,
      duration: 100,
      onClose() {
        baseMap.current?.clearFeatures(TEMPORARY_LAYER);
        baseMap.current?.toggleLayer(DATA_LAYER, true);
        baseMap.current?.zoomToFeaturesInLayer(DATA_LAYER);
      },
      style: {
        width:
          window.innerWidth <= 576
            ? '80vw'
            : window.innerWidth <= 768
            ? '60vw'
            : '800px',
        maxWidth: '800px',
        height: 'auto',
        borderRadius: '12px',
        boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
      },
    });
  };

  const onFeaturesClick = useCallback((features: Feature[]) => {
    console.log('Multiple features clicked:', features);
    const things: SgwModel.SgwThing[] = features.map((feature) =>
      feature.get('thing'),
    ) as SgwModel.SgwThing[];
    setMultipleThingsSelected(things);
    setShowMultiShipsDrawer(true);
  }, []);

  const onFeatureClick = useCallback(
    (feature: Feature) => {
      const thing: SgwModel.SgwThing = feature.get('thing');
      baseMap.current?.zoomToFeatures([feature]);
      handleClickOneThing(thing);
    },
    [baseMap],
  );

  const onError = useCallback(
    (error: any) => {
      console.error(
        intl.formatMessage({ id: 'home.mapError' }),
        'at',
        new Date().toLocaleTimeString(),
        ':',
        error,
      );
    },
    [intl],
  );

  // Handler called when map is ready
  const handleMapReady = useCallback((baseMapInstance: BaseMap) => {
    // console.log('Map is ready!', baseMapInstance);
    baseMap.current = baseMapInstance;
    // Create a vector layer for dynamic features
    const vectorDataLayer = new VectorLayer({
      source: new VectorSource(),
    });
    vectorDataLayer.set('id', DATA_LAYER);
    const vectorTemporaryLayer = new VectorLayer({
      source: new VectorSource(),
    });
    vectorTemporaryLayer.set('id', TEMPORARY_LAYER);

    baseMapInstance.addLayer(vectorDataLayer);
    baseMapInstance.addLayer(vectorTemporaryLayer);
    getShipSosWs();
  }, []);

  useEffect(() => {
    if (shipSos !== null && things && things.things) {
      const check = things?.things?.find(
        (thing) => thing.id === shipSos.thing_id,
      );
      if (check) {
        tableRef.current?.reload();
      }
    }
  }, [shipSos]);

  useEffect(() => {
    if (formSearchData && tableRef.current) {
      tableRef.current.reload(); // gọi lại request
    }
  }, [formSearchData]);

  const queryThings = async (params: ParamsType) => {
    try {
      const { current = 1, pageSize = 10, keyword = '' } = params;
      const offset = current === 1 ? 0 : (current - 1) * pageSize;
      const query: MasterModel.SearchThingPaginationBody = {
        offset: offset,
        limit: 200,
        order: 'name',
        dir: 'asc',
      };
      const stateNormalQuery = stateQuery?.isNormal ? 'normal' : '';
      const stateSosQuery = stateQuery?.isSos ? 'sos' : '';
      const stateWarningQuery = stateQuery?.isWarning
        ? stateNormalQuery + ',warning'
        : stateNormalQuery;
      const stateCriticalQuery = stateQuery?.isCritical
        ? stateWarningQuery + ',critical'
        : stateWarningQuery;
      const stateQueryParams =
        stateQuery?.isNormal &&
        stateQuery?.isWarning &&
        stateQuery?.isCritical &&
        stateQuery?.isSos
          ? ''
          : [stateCriticalQuery, stateSosQuery].filter(Boolean).join(',');
      let metaFormQuery: Record<string, any> = {};
      if (stateQuery?.isDisconnected)
        metaFormQuery = { ...metaFormQuery, connected: false };
      const metaStateQuery =
        stateQueryParams !== '' ? { state_level: stateQueryParams } : null;
      if (formSearchData) {
        const {
          ship_name,
          reg_number,
          ship_length,
          ship_power,
          ship_type,
          alarm_list,
          group_id,
          ship_group_id,
        } = formSearchData;

        if (ship_name) metaFormQuery.ship_name = ship_name;
        if (reg_number) metaFormQuery.ship_reg_number = reg_number;
        if (Array.isArray(ship_length) && ship_length.length === 2) {
          metaFormQuery.ship_length = ship_length;
        }
        if (Array.isArray(ship_power) && ship_power.length === 2) {
          metaFormQuery.ship_power = ship_power;
        }
        if (Array.isArray(ship_type) && ship_type.length > 0) {
          metaFormQuery.ship_type = ship_type;
        }
        if (Array.isArray(alarm_list) && alarm_list.length > 0) {
          metaFormQuery.alarm_list = alarm_list;
        }
        if (group_id) metaFormQuery.group_id = group_id;
        if (Array.isArray(ship_group_id) && ship_group_id.length > 0) {
          metaFormQuery.ship_group_id = ship_group_id;
        }
      }
      const metaQuery = {
        ...query,
        metadata: {
          ship_name: keyword,
          ...metaFormQuery,
          ...metaStateQuery,
          not_empty: 'ship_id',
        },
      };

      setThings(null);
      const resp = await apiSearchThings(metaQuery, 'sgw');
      return resp;
    } catch (error) {
      console.error('Error when searchThings: ', error);
      return {};
    }
  };

  const handleZoomToFeature = (layerName: string) => {
    if (!baseMap) return;

    // Get all features and zoom to them
    const vectorLayer = baseMap.current?.getLayerById(layerName);
    if (vectorLayer && vectorLayer instanceof VectorLayer) {
      const features = vectorLayer.getSource()?.getFeatures();
      if (features && features.length > 0) {
        baseMap.current?.zoomToFeatures(features);
      }
    }
  };

  useEffect(() => {
    if (!things || !baseMap.current || !things.things) return;
    // Cleanup các animation và overlay cũ trước khi render lại
    sosPulseCancelRefs.current.forEach((cancel) => cancel());
    sosPulseCancelRefs.current = [];
    overlayCleanupRefs.current.forEach((cleanup) => cleanup());
    overlayCleanupRefs.current.clear();
    baseMap.current.clearOverlays();

    baseMap.current.clearFeatures(DATA_LAYER);
    for (const thing of things.things) {
      const gpsData: GPSParseResult = JSON.parse(thing.metadata?.gps || '{}');
      if (gpsData.lat && gpsData.lon) {
        if (thing.metadata?.state_level === 3) {
          console.log('Cos tau sos');
          const feature = baseMap.current?.addPoint(
            DATA_LAYER,
            [gpsData.lon, gpsData.lat],
            {
              thing,
              type: 'sos-point',
            },
          );
          // Bắt đầu hiệu ứng gợn sóng
          const cancel = baseMap.current?.sosPulse(feature, DATA_LAYER);
          if (cancel) {
            sosPulseCancelRefs.current.push(cancel);
          }
          // Tạo overlay hiển thị thông tin SOS
          const overlayElement = document.createElement('div');
          const cleanup = renderSosOverlay(overlayElement, {
            shipName: thing.metadata?.ship_name || thing.name,
            reason: thing.metadata.sos || 'Không rõ lý do',
            time: thing.metadata?.sos_time
              ? formatUnixTime(thing.metadata.sos_time)
              : undefined,
          });
          overlayCleanupRefs.current.set(thing.id!, cleanup);
          baseMap.current.addOrUpdateOverlay(
            `sos-${thing.id}`,
            [gpsData.lon, gpsData.lat],
            overlayElement,
          );
        } else {
          baseMap.current?.addPoint(DATA_LAYER, [gpsData.lon, gpsData.lat], {
            thing,
            type: 'main-point',
          });
        }
      }
    }
    handleZoomToFeature(DATA_LAYER);
    // Cleanup khi component unmount
    return () => {
      sosPulseCancelRefs.current.forEach((cancel) => cancel());
      sosPulseCancelRefs.current = [];
      overlayCleanupRefs.current.forEach((cleanup) => cleanup());
      overlayCleanupRefs.current.clear();
    };
  }, [things]);

  const columns: ProColumns<SgwModel.SgwThing>[] = [
    {
      title: intl.formatMessage({
        id: 'thing.name',
        defaultMessage: 'Name',
      }),
      dataIndex: ['metadata', 'ship_name'],
      key: 'ship_name',
      hideInSearch: true,
      width: '30%',
      ellipsis: true,
      render: (_, row) => {
        const text = row?.metadata?.ship_name || '';
        return (
          <Tooltip title={text}>
            <span
              style={{
                color: getShipNameColor(row?.metadata?.state_level || 0),
              }}
            >
              {text}
            </span>
          </Tooltip>
        );
      },
    },
    {
      title: intl.formatMessage({
        id: 'thing.status',
        defaultMessage: 'Status',
      }),
      dataIndex: ['metadata', 'state_level'],
      key: 'status',
      hideInSearch: true,
      width: '70%',
      filters: true,
      onFilter: true,
      valueType: 'select',
      valueEnum: {
        0: {
          text: intl.formatMessage({
            id: 'thing.status.normal',
            defaultMessage: 'Normal',
          }),
          status: 'Normal',
        },
        1: {
          text: intl.formatMessage({
            id: 'thing.status.warning',
            defaultMessage: 'Warning',
          }),
          status: 'Warning',
        },
        2: {
          text: intl.formatMessage({
            id: 'thing.status.critical',
            defaultMessage: 'Critical',
          }),
          status: 'Critical',
        },
        3: {
          text: intl.formatMessage({
            id: 'thing.status.sos',
            defaultMessage: 'SOS',
          }),
          status: 'SOS',
        },
      },
      ellipsis: true,
      render: (_, row) => {
        const alarm = JSON.parse(row?.metadata?.alarm_list || '{}');
        const text = alarm?.map((a: any) => a?.name).join(', ');
        return (
          <Tooltip placement="top" title={text}>
            {getBadgeStatus(row?.metadata?.state_level || 0)}
            <span className="ml-2 text-gray-500">{text}</span>
          </Tooltip>
        );
      },
    },
  ];

  const handleTagStateChange = (payload: TagStateCallbackPayload) => {
    setStateQuery(payload);
    tableRef.current?.reload();
  };

  return (
    <div className="h-screen w-screen relative">
      {contextHolder}
      {messageContextHolder}
      <div
        style={{
          position: 'absolute',
          top: 5,
          left: 2,
          zIndex: 10,
          borderRadius: 10,
          boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
          backgroundColor: token.token.colorBgContainer,
          width: isCollapsed ? '28%' : '30%',
          minWidth: '25%',
          maxWidth: '30%',
          overflowX: 'auto',
          whiteSpace: 'nowrap',
          transition: 'width 0.5s ease-in-out',
        }}
      >
        <div>
          <Flex
            justify="space-between"
            gap={30}
            align="center"
            style={{
              width: '100%',
              padding: '8px 12px',
            }}
          >
            <Flex gap={8} align="center">
              <Button
                type="text"
                icon={isCollapsed ? <DownOutlined /> : <UpOutlined />}
                onClick={() => setIsCollapsed(!isCollapsed)}
                style={{ padding: '4px 8px' }}
              />
              {formSearchData === null ? (
                <Button
                  icon={<FilterOutlined />}
                  onClick={(e) => {
                    e.stopPropagation();
                    messageApi.destroy();
                    setOpenFormSearch(true);
                  }}
                />
              ) : (
                <Tag
                  style={{
                    cursor: 'pointer',
                    fontSize: '12px',
                    padding: '4px 8px',
                    lineHeight: '20px',
                    minWidth: '0',
                    overflow: 'hidden',
                    textOverflow: 'ellipsis',
                  }}
                  onClick={(e) => {
                    e.stopPropagation();
                    messageApi.destroy();
                    setOpenFormSearch(true);
                  }}
                  closeIcon
                  onClose={(e) => {
                    e.stopPropagation();
                    setFormSearchData(null);
                    if (tableRef.current) {
                      tableRef.current.reload();
                    }
                  }}
                  color="#87d068"
                >
                  Tìm theo bộ lọc
                </Tag>
              )}
            </Flex>
            {isCollapsed && (
              <div onClick={(e) => e.stopPropagation()}>
                <TagState
                  normalCount={things?.metadata?.total_state_level_0 || 0}
                  warningCount={things?.metadata?.total_state_level_1 || 0}
                  criticalCount={things?.metadata?.total_state_level_2 || 0}
                  sosCount={things?.metadata?.total_sos || 0}
                  disconnectedCount={
                    (things?.metadata?.total_thing ?? 0) -
                      (things?.metadata?.total_connected ?? 0) || 0
                  }
                  onTagPress={handleTagStateChange}
                />
              </div>
            )}
          </Flex>
          <ProTable<SgwModel.SgwThing>
            tableClassName="table-row-select cursor-pointer-row"
            actionRef={tableRef}
            toolbar={{
              title: null,
              actions: [
                <TagState
                  key="tag-state"
                  normalCount={things?.metadata?.total_state_level_0 || 0}
                  warningCount={things?.metadata?.total_state_level_1 || 0}
                  criticalCount={things?.metadata?.total_state_level_2 || 0}
                  sosCount={things?.metadata?.total_sos || 0}
                  disconnectedCount={
                    (things?.metadata?.total_thing ?? 0) -
                      (things?.metadata?.total_connected ?? 0) || 0
                  }
                  onTagPress={handleTagStateChange}
                />,
              ],
            }}
            bordered={true}
            polling={DURATION_POLLING_PRESENTATIONS}
            style={{
              display: isCollapsed ? 'none' : 'block',
            }}
            pagination={{
              size: 'small',
              defaultPageSize: 10,
              showSizeChanger: true,
              pageSizeOptions: ['10', '15', '20'],
              showTotal: (total, range) =>
                `${range[0]}-${range[1]} trên ${total} ${intl.formatMessage({
                  id: 'thing.ships',
                  defaultMessage: 'ships',
                })}`,
            }}
            columns={columns}
            request={async (params: ParamsType) => {
              const data = await queryThings(params);
              const sortedThings = [...(data.things || [])].sort((a, b) => {
                const stateLevelA = a.metadata?.state_level || 0;
                const stateLevelB = b.metadata?.state_level || 0;
                return stateLevelB - stateLevelA;
              });
              setThings(data);
              return Promise.resolve({
                success: true,
                data: sortedThings,
                total: data?.metadata?.total_filter || 0,
              });
            }}
            onRow={(row) => {
              return {
                onClick: () => {
                  handleClickOneThing(row);
                },
              };
            }}
            rowClassName={(record) =>
              record?.metadata?.state_level
                ? 'cursor-pointer'
                : `${styles.disconnected} cursor-pointer`
            }
            options={{
              search: false,
              setting: false,
              density: false,
              reload: true,
            }}
            defaultSize="small"
            search={false}
            rowKey="id"
            dateFormatter="string"
          />
        </div>
      </div>

      {/* VietNamMap with ref */}
      <VietNamMap
        ref={vietNamMapRef}
        style={{
          height: '100vh',
          width: '100vw',
        }}
        onMapReady={handleMapReady}
        onFeatureClick={onFeatureClick}
        onFeaturesClick={onFeaturesClick}
        onError={onError}
      />
      <Drawer
        styles={{
          header: {
            padding: 5,
          },
        }}
        open={showMultiShipsDrawer}
        onClose={() => {
          setShowMultiShipsDrawer(false);
          setMultipleThingsSelected([]);
        }}
        title={
          <Flex align="center" justify="center">
            <Typography.Title level={4}>
              Thông tin {multipleThingsSelected.length} tàu
            </Typography.Title>
          </Flex>
        }
        size="large"
      >
        <MultipleShips
          things={multipleThingsSelected}
          messageApi={messageApi}
          mapController={baseMap.current}
        />
      </Drawer>
      <ShipSearchForm
        initialValues={formSearchData || undefined}
        isModalOpen={openFormSearch}
        onClose={setOpenFormSearch}
        things={things?.things || []}
        onSubmit={(value: SearchShipResponse) => {
          setFormSearchData(value);
        }}
      />
    </div>
  );
};

export default MapPage;
