import React, { useCallback, useEffect, useRef, useState } from "react";
import { Collapse, Empty, Table as AntdTable } from "antd";
import "./Table.css";
import { useQuery } from "@tanstack/react-query";
import { api } from "../../api";
import parse from "wellknown";
import { useMap } from "react-map-gl";
import { usePointSelection } from "../../stores/usePointSelection";
import { useFilters } from "../../stores/useFilters";
import { useClickedPointConfig } from "../../stores/useClickedPointConfig";
import scrollIntoView from "scroll-into-view-if-needed";

const columns = [
  {
    title: "Id",
    dataIndex: "location_id",
    key: "location_id",
    width: 50,
    ellipsis: true,
  },
  {
    title: "Адрес",
    dataIndex: "address",
    key: "address",
    width: 200,
  },
  {
    title: "Район",
    dataIndex: "rayon",
    key: "rayon",
    width: "120px",
    ellipsis: true,
  },
  {
    title: "Округ",
    dataIndex: "okrug",
    key: "okrug",
    width: "120px",
    ellipsis: true,
  },
  {
    title: "Название",
    dataIndex: "name",
    key: "name",
    width: "120px",
    ellipsis: true,
  },
  {
    title: "Категория",
    dataIndex: "category",
    key: "category",
    width: "120px",
    ellipsis: true,
  },
  {
    title: "Статус",
    dataIndex: "status",
    key: "status",
    width: "120px",
    ellipsis: true,
  },
  {
    title: "Прогнозный трафик",
    dataIndex: "prediction_current",
    key: "prediction_current",
    width: "120px",
    ellipsis: true,
  },
];

const PAGE_SIZE = 30;

const useTableData = (page) => {
  const [pageSize, setPageSize] = useState(PAGE_SIZE);
  const { filters } = useFilters();
  const { prediction, status, categories, region } = filters;
  const { selection } = usePointSelection();
  const { clickedPointConfig } = useClickedPointConfig();
  const [finalData, setFinalData] = useState();

  const { data } = useQuery(
    ["table", page, filters, selection],
    async () => {
      const params = new URLSearchParams({
        page,
        page_size: pageSize,
        "prediction_current[]": prediction,
        "status[]": status,
        "categories[]": categories,
        "included[]": [...selection.included],
      });

      if (region) {
        if (region.type === "ao") {
          params.append("ao[]", region.id);
        }

        if (region.type === "rayon") {
          params.append("rayon[]", region.id);
        }
      }

      const { data } = await api.get(
        `/api/placement_points?${params.toString()}`
      );

      return data;
    },
    { keepPreviousData: true }
  );

  useEffect(() => {
    if (!data) return;

    setFinalData(data);
  }, [data]);

  const [shouldLoadClickedPoint, setShouldLoadClickedPoint] = useState(false);

  useEffect(() => {
    if (!data || clickedPointConfig === null) return;

    const clickedPoint = data.results.find(
      (item) => item.location_id === clickedPointConfig.id
    );

    if (clickedPoint) {
      return;
    }

    setShouldLoadClickedPoint(true);
  }, [data, clickedPointConfig]);

  const {
    data: remoteClickedPoint,
    isInitialLoading,
    isFetching,
  } = useQuery(
    ["clicked-point", clickedPointConfig],
    async () => {
      const params = new URLSearchParams({
        "location_ids[]": [clickedPointConfig.id],
      });

      const { data } = await api.get(
        `/api/placement_points?${params.toString()}`
      );

      return data;
    },
    {
      enabled: shouldLoadClickedPoint,
      onSuccess: () => setShouldLoadClickedPoint(false),
    }
  );

  useEffect(() => {
    if (!remoteClickedPoint) return;

    setPageSize((prevState) => prevState + 1);
    setFinalData((prevState) => ({
      ...prevState,
      count: prevState.count + 1,
      results: [remoteClickedPoint.results[0], ...prevState.results],
    }));
  }, [remoteClickedPoint]);

  useEffect(() => {
    if (clickedPointConfig === null) {
      setPageSize(PAGE_SIZE);
      setFinalData(data);
    }
  }, [clickedPointConfig]);

  return {
    data: finalData,
    pageSize,
    isClickedPointLoading: isInitialLoading || isFetching,
  };
};

export const Table = React.memo(({ height = 200 }) => {
  const { map } = useMap();
  const tableRef = useRef(null);
  const [page, setPage] = useState(1);
  const { selection, include, exclude } = usePointSelection();
  const { clickedPointConfig } = useClickedPointConfig();

  const { data, pageSize, isClickedPointLoading } = useTableData(page);

  const SCROLL = {
    y: `${height}px`,
    x: "max-content",
  };

  const handlePageChange = useCallback((page) => setPage(page), []);

  const getSelectedRowKeys = useCallback(() => {
    const ids = data?.results.map((item) => item.location_id) ?? [];
    const clickedPoint = data?.results.find(
      (item) => item.location_id === clickedPointConfig?.id
    );

    const inExcludedList = (id) => selection.excluded.has(id);
    const shouldNotSelect = (id) =>
      id === clickedPoint?.id && clickedPointConfig?.shouldSelect === false;

    return [
      ...ids.filter((id) => {
        return !inExcludedList(id) && !shouldNotSelect(id);
      }),
      ...selection.included,
    ];
  }, [data, clickedPointConfig, selection]);

  const rowSelection = {
    selectedRowKeys: getSelectedRowKeys(),
    onSelect: (record, selected) => {
      const { location_id: id } = record;
      if (selected) {
        include(id);
      } else {
        exclude(id);
      }
    },
    hideSelectAll: true,
  };

  useEffect(() => {
    if (clickedPointConfig === null || isClickedPointLoading) return;

    const row = document.querySelector(".scroll-row");
    if (row) {
      scrollIntoView(row, { behavior: "smooth" });
    }
  }, [clickedPointConfig, data]);

  return (
    <div className="w-screen">
      <Collapse>
        <Collapse.Panel key="1" header="Таблица атрибутов">
          <AntdTable
            ref={tableRef}
            className="table"
            size="small"
            // rowSelection={rowSelection}
            locale={{ emptyText: <Empty description="Нет данных" /> }}
            // loading={isLoading}
            pagination={{
              pageSize,
              current: page,
              onChange: handlePageChange,
              total: data?.count,
              showSizeChanger: false,
              position: "bottomCenter",
            }}
            dataSource={data?.results}
            columns={columns}
            rowKey="location_id"
            scroll={SCROLL}
            sticky={true}
            onRow={(record) => {
              return {
                onClick: () => {
                  const geometry = parse(record.geometry);
                  map.flyTo({
                    center: [geometry.coordinates[0], geometry.coordinates[1]],
                    zoom: 15,
                    speed: 5,
                  });
                },
              };
            }}
            rowSelection={rowSelection}
            rowClassName={(record) =>
              record.location_id === clickedPointConfig?.id ? "scroll-row" : ""
            }
          />
        </Collapse.Panel>
      </Collapse>
    </div>
  );
});
