import { render, act } from "@testing-library/react";
import FlightServiceComponent from "./FlightServiceComponent";
import useMissionControlStore from "./stores/mission_control";

describe("FlightServiceComponent", () => {
  let messageHandler;

  beforeEach(() => {
    // Mock Whitebox.sockets
    globalThis.Whitebox = {
      ...(globalThis.Whitebox || {}),
      sockets: {
        addEventListener: vi.fn((channel, type, handler) => {
          if (channel === "flight" && type === "message") {
            messageHandler = handler;
          }
        }),
        removeEventListener: vi.fn(),
      },
    };
  });

  it("should set up WebSocket event listener on mount", () => {
    render(<FlightServiceComponent />);

    expect(Whitebox.sockets.addEventListener).toHaveBeenCalledWith(
      "flight",
      "message",
      expect.any(Function)
    );
  });

  it("should update mission control store on receiving flight.start event", async () => {
    const mockSetActiveFlightSession = vi.fn();
    await act(async () => {
      await useMissionControlStore.setState({
        setActiveFlightSession: mockSetActiveFlightSession,
      })
    });

    render(<FlightServiceComponent />);

    act(() => {
      // Simulate receiving a message
      messageHandler({
        data: JSON.stringify({
          type: "flight.start",
          flight_session: {
            id: 1,
            name: "Test Flight",
          },
        }),
      });
    })

    expect(mockSetActiveFlightSession).toHaveBeenCalledWith({
      id: 1,
      name: "Test Flight",
    });
  });

  it("clears key moment pending state after record when list shows active key moment", async () => {
    const mockSetSessionKeyMoments = vi.fn();
    const mockClearKeyMomentPendingAction = vi.fn();
    const keyMoments = [
      {
        id: 99,
        started_at: "2025-01-01T00:00:00Z",
        ended_at: null,
      },
    ];

    await act(async () => {
      await useMissionControlStore.setState({
        activeFlightSession: { id: 1 },
        keyMomentPendingAction: "record",
        setSessionKeyMoments: mockSetSessionKeyMoments,
        clearKeyMomentPendingAction: mockClearKeyMomentPendingAction,
      });
    });

    render(<FlightServiceComponent />);

    act(() => {
      messageHandler({
        data: JSON.stringify({
          type: "flight.key_moment.list",
          flight_session_id: 1,
          key_moments: keyMoments,
        }),
      });
    });

    expect(mockSetSessionKeyMoments).toHaveBeenCalledWith(keyMoments);
    expect(mockClearKeyMomentPendingAction).toHaveBeenCalledTimes(1);
  });

  it("clears key moment pending state after finish when list shows no active key moment", async () => {
    const mockSetSessionKeyMoments = vi.fn();
    const mockClearKeyMomentPendingAction = vi.fn();
    const keyMoments = [
      {
        id: 99,
        started_at: "2025-01-01T00:00:00Z",
        ended_at: "2025-01-01T00:05:00Z",
      },
    ];

    await act(async () => {
      await useMissionControlStore.setState({
        activeFlightSession: { id: 1 },
        keyMomentPendingAction: "finish",
        setSessionKeyMoments: mockSetSessionKeyMoments,
        clearKeyMomentPendingAction: mockClearKeyMomentPendingAction,
      });
    });

    render(<FlightServiceComponent />);

    act(() => {
      messageHandler({
        data: JSON.stringify({
          type: "flight.key_moment.list",
          flight_session_id: 1,
          key_moments: keyMoments,
        }),
      });
    });

    expect(mockSetSessionKeyMoments).toHaveBeenCalledWith(keyMoments);
    expect(mockClearKeyMomentPendingAction).toHaveBeenCalledTimes(1);
  });

  it("does not clear key moment pending state when list does not reflect pending transition", async () => {
    const mockSetSessionKeyMoments = vi.fn();
    const mockClearKeyMomentPendingAction = vi.fn();
    const keyMoments = [
      {
        id: 99,
        started_at: "2025-01-01T00:00:00Z",
        ended_at: "2025-01-01T00:05:00Z",
      },
    ];

    await act(async () => {
      await useMissionControlStore.setState({
        activeFlightSession: { id: 1 },
        keyMomentPendingAction: "record",
        setSessionKeyMoments: mockSetSessionKeyMoments,
        clearKeyMomentPendingAction: mockClearKeyMomentPendingAction,
      });
    });

    render(<FlightServiceComponent />);

    act(() => {
      messageHandler({
        data: JSON.stringify({
          type: "flight.key_moment.list",
          flight_session_id: 1,
          key_moments: keyMoments,
        }),
      });
    });

    expect(mockSetSessionKeyMoments).toHaveBeenCalledWith(keyMoments);
    expect(mockClearKeyMomentPendingAction).not.toHaveBeenCalled();
  });

  it("stores key moment error when websocket reports key moment failure", async () => {
    const mockSetKeyMomentPendingError = vi.fn();

    await act(async () => {
      await useMissionControlStore.setState({
        setKeyMomentPendingError: mockSetKeyMomentPendingError,
      });
    });

    render(<FlightServiceComponent />);

    act(() => {
      messageHandler({
        data: JSON.stringify({
          type: "error",
          event_type: "flight.key_moment.finish",
          message: "Cannot finish key moment",
        }),
      });
    });

    expect(mockSetKeyMomentPendingError).toHaveBeenCalledWith(
      "Cannot finish key moment"
    );
  });
});
