import { act, fireEvent, render, screen, waitFor } from "@testing-library/react";
import SchemeEditor from "./SchemeEditor";
import type { SensorPlacementScheme } from "./types";

const mockOpen = jest.fn();
let mockSingleClickHandler: ((event: unknown) => void) | undefined;

const mockMap = {
  addLayer: jest.fn(),
  removeLayer: jest.fn(),
  on: jest.fn((eventName: string, handler: (event: unknown) => void) => {
    if (eventName === "singleclick") {
      mockSingleClickHandler = handler;
    }
  }),
  un: jest.fn(),
  forEachFeatureAtPixel: jest.fn(() => undefined),
  getView: jest.fn(() => ({
    animate: jest.fn(),
    getZoom: jest.fn(() => 16),
    getResolution: jest.fn(() => 1),
  })),
};

jest.mock("@refinedev/core", () => ({
  useNotification: () => ({ open: mockOpen }),
}));

jest.mock("@components/olmap/core/MapComponent", () => ({
  useMap: () => mockMap,
}));

jest.mock("@mui/x-data-grid", () => ({
  DataGrid: (props: {
    density?: string;
    initialState?: { density?: string };
    rowHeight?: number;
    columnHeaderHeight?: number;
  }) => (
    <div
      data-testid="scheme-grid"
      data-density={props.density ?? "uncontrolled"}
      data-initial-density={props.initialState?.density ?? ""}
      data-row-height={props.rowHeight ?? "automatic"}
      data-column-header-height={props.columnHeaderHeight ?? "automatic"}
    />
  ),
  GridToolbar: () => null,
}));

jest.mock("@mui/x-data-grid/locales", () => ({
  zhCN: {
    components: {
      MuiDataGrid: {
        defaultProps: {
          localeText: {},
        },
      },
    },
  },
}));

jest.mock("ol/Feature", () => ({
  __esModule: true,
  default: class {
    private values: Record<string, unknown>;

    constructor(values: Record<string, unknown>) {
      this.values = values;
    }

    get(key: string) {
      return this.values[key];
    }

    setId() {}
  },
}));

jest.mock("ol/geom/Point", () => ({
  __esModule: true,
  default: class {
    constructor(_coordinates: number[]) {}
  },
}));

jest.mock("ol/source/Vector", () => ({
  __esModule: true,
  default: class {
    clear() {}
    addFeature() {}
  },
}));

jest.mock("ol/layer/Vector", () => ({
  __esModule: true,
  default: class {
    private source: { clear: () => void; addFeature: () => void };

    constructor(options: {
      source: { clear: () => void; addFeature: () => void };
    }) {
      this.source = options.source;
    }

    getSource() {
      return this.source;
    }

    setVisible() {}
  },
}));

jest.mock("ol/style", () => ({
  Circle: class {},
  Fill: class {},
  Stroke: class {},
  Style: class {},
  Text: class {},
}));

jest.mock("ol/proj", () => ({
  fromLonLat: (coordinates: number[]) => coordinates,
  toLonLat: (coordinates: number[]) => coordinates,
}));

jest.mock("@/utils/mapQueryService", () => ({
  handleMapClickSelectFeatures: jest.fn(),
}));

jest.mock("./SchemeDrawingDialog", () => ({
  __esModule: true,
  default: () => null,
}));

jest.mock("./schemeApi", () => ({
  exportSensorPlacementExcel: jest.fn(),
  overwriteSensorPlacementScheme: jest.fn(),
}));

const scheme: SensorPlacementScheme = {
  id: 1,
  scheme_name: "测试方案",
  sensor_number: 1,
  min_diameter: 300,
  username: "operator",
  create_time: "2026-07-30T08:00:00+08:00",
  sensor_location: ["J1"],
  sensor_points: [
    {
      node_id: "J1",
      project_x: 10,
      project_y: 20,
      map_x: 13500010,
      map_y: 3600020,
      longitude: 121,
      latitude: 31,
      elevation: 5,
    },
  ],
  can_edit: true,
};

describe("SchemeEditor notifications", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockSingleClickHandler = undefined;
  });

  it("uses the same error notification contract as scheme query when replace starts outside an existing sensor", async () => {
    render(<SchemeEditor scheme={scheme} network="fengyang" />);

    fireEvent.click(screen.getByRole("button", { name: "替换" }));
    await waitFor(() => expect(mockSingleClickHandler).toBeDefined());

    act(() => {
      mockSingleClickHandler?.({
        pixel: [0, 0],
        coordinate: [13500000, 3600000],
        stopPropagation: jest.fn(),
      });
    });

    expect(mockOpen).toHaveBeenCalledWith({
      type: "error",
      message: "请先点击要替换的监测点",
    });
  });

  it("lets the Data Grid density selector control row sizing", () => {
    render(<SchemeEditor scheme={scheme} network="fengyang" />);

    expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
      "data-density",
      "uncontrolled",
    );
    expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
      "data-initial-density",
      "compact",
    );
    expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
      "data-row-height",
      "automatic",
    );
    expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
      "data-column-header-height",
      "automatic",
    );
  });
});
