import { act, render, screen, waitFor } from "@testing-library/react";
import { Arrival } from "./Arrival";
import { MemoryRouter } from "react-router-dom";
import { useFetchArrival } from "../../hooks/useFetchArrival";
import '@testing-library/jest-dom'; // Import the necessary matchers

jest.mock("../../hooks/useFetchArrival");

const mockedUseFetchArrival = useFetchArrival as jest.MockedFunction<typeof useFetchArrival>;

describe("Arrival Component Tests", () => {
    test("Renders Arrival component with headers", () => {
        mockedUseFetchArrival.mockReturnValue({ zones: [], error: null });

        render(
            <MemoryRouter>
                <Arrival />
            </MemoryRouter>
        );

        expect(screen.getByText("Arrival")).toBeInTheDocument();
        expect(screen.getByText("Code")).toBeInTheDocument();
        expect(screen.getByText("Origin")).toBeInTheDocument();
        expect(screen.getByText("Time")).toBeInTheDocument();
        expect(screen.getByText("Gate")).toBeInTheDocument();
        expect(screen.getByText("Status")).toBeInTheDocument();
    });

    test("Renders error message when there is an error", async () => {
        mockedUseFetchArrival.mockReturnValue({ zones: [], error: "Error fetching data" });

        render(
            <MemoryRouter>
                <Arrival />
            </MemoryRouter>
        );

        await waitFor(() => {
            expect(screen.getByText("Error fetching data")).toBeInTheDocument();
        });
    });

    test("Doesn't throw an error when no data is available", async () => {
        mockedUseFetchArrival.mockReturnValue({ zones: [], error: null });

        render(
            <MemoryRouter>
                <Arrival />
            </MemoryRouter>
        );

        await waitFor(() => {
            expect(screen.queryByText("ABC123")).not.toBeInTheDocument();
            expect(screen.queryByText("City A")).not.toBeInTheDocument();
            expect(screen.queryByText("2023-10-30 12:00 PM")).not.toBeInTheDocument();
            expect(screen.queryByText("A1")).not.toBeInTheDocument();
            expect(screen.queryByText("On Time")).not.toBeInTheDocument();

        })
    });

    test("Renders flights when data is available", async () => {
        const mockFlights = [
            {
                id: 1,
                flight_code: "ABC123",
                origin: "City A",
                destination: "City X",
                departure_time: "2023-10-30 10:00 AM",
                arrival_time: "2023-10-30 12:00 PM",
                gate: "A1",
                status: "On Time"
            },
            {
                id: 2,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
        ];

        mockedUseFetchArrival.mockReturnValue({ zones: mockFlights, error: null });

        render(
            <MemoryRouter>
                <Arrival />
            </MemoryRouter>
        );

        await waitFor(() => {
            expect(screen.getByText("ABC123")).toBeInTheDocument();
            expect(screen.getByText("City A")).toBeInTheDocument();
            expect(screen.getByText("2023-10-30 12:00 PM")).toBeInTheDocument();
            expect(screen.getByText("A1")).toBeInTheDocument();
            expect(screen.getByText("On Time")).toBeInTheDocument();

            expect(screen.getByText("XYZ789")).toBeInTheDocument();
            expect(screen.getByText("City B")).toBeInTheDocument();
            expect(screen.getByText("2023-10-31 02:30 PM")).toBeInTheDocument();
            expect(screen.getByText("B2")).toBeInTheDocument();
            expect(screen.getByText("Delayed")).toBeInTheDocument();
        });
    });

    jest.setTimeout(20000);

    test("Automatically cycles through flights with an interval", async () => {
        const mockFlights = [
            {
                id: 1,
                flight_code: "ABC123",
                origin: "City A",
                destination: "City X",
                departure_time: "2023-10-30 10:00 AM",
                arrival_time: "2023-10-30 12:00 PM",
                gate: "A1",
                status: "On Time"
            },
            {
                id: 2,
                flight_code: "XYZ788",
                origin: "City C",
                destination: "City Y",
                departure_time: "2023-10-31 01:31 PM",
                arrival_time: "2023-10-31 02:31 PM",
                gate: "B3",
                status: "Scheduled"
            },
            {
                id: 3,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 4,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 5,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 6,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 7,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 8,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 9,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 10,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
            {
                id: 11,
                flight_code: "XYZ789",
                origin: "City B",
                destination: "City Y",
                departure_time: "2023-10-31 01:30 PM",
                arrival_time: "2023-10-31 02:30 PM",
                gate: "B2",
                status: "Delayed"
            },
        ];


        mockedUseFetchArrival.mockReturnValue({ zones: mockFlights, error: null });

        render(
            <MemoryRouter>
                <Arrival />
            </MemoryRouter>
        );

        await waitFor(() => {
            expect(screen.getByText("ABC123")).toBeInTheDocument();
            expect(screen.getByText("City A")).toBeInTheDocument();
            expect(screen.getByText("2023-10-30 12:00 PM")).toBeInTheDocument();
            expect(screen.getByText("A1")).toBeInTheDocument();
            expect(screen.getByText("On Time")).toBeInTheDocument();

            expect(screen.queryByText("XYZ788")).toBeInTheDocument();
            expect(screen.queryByText("City C")).toBeInTheDocument();
            expect(screen.queryByText("2023-10-31 02:31 PM")).toBeInTheDocument();
            expect(screen.queryByText("B3")).toBeInTheDocument();
            expect(screen.queryByText("Scheduled")).toBeInTheDocument();
        });

        await act(async () => {
            await new Promise(resolve => setTimeout(resolve, 5000));
        });


        await waitFor(() => {
            expect(screen.queryByText("ABC123")).not.toBeInTheDocument();
            expect(screen.queryByText("City A")).not.toBeInTheDocument();
            expect(screen.queryByText("2023-10-30 12:00 PM")).not.toBeInTheDocument();
            expect(screen.queryByText("A1")).not.toBeInTheDocument();
            expect(screen.queryByText("On Time")).not.toBeInTheDocument();

            expect(screen.queryByText("XYZ788")).not.toBeInTheDocument();
            expect(screen.queryByText("City C")).not.toBeInTheDocument();
            expect(screen.queryByText("2023-10-31 02:31 PM")).not.toBeInTheDocument();
            expect(screen.queryByText("B3")).not.toBeInTheDocument();
            expect(screen.queryByText("Scheduled")).not.toBeInTheDocument();

            expect(screen.getByText("XYZ789")).toBeInTheDocument();
            expect(screen.getByText("City B")).toBeInTheDocument();
            expect(screen.getByText("2023-10-31 02:30 PM")).toBeInTheDocument();
            expect(screen.getByText("B2")).toBeInTheDocument();
            expect(screen.getByText("Delayed")).toBeInTheDocument();
        });
    });
});