import { render, screen, waitFor } from "@testing-library/react";
import AppointmentsList from "@/app/[lang]/dashboard/components/AppointmentsList";

// Mock next/dynamic — render all lazy-loaded modals as simple stubs
jest.mock("next/dynamic", () => {
  return (_loader: () => Promise<{ default: React.ComponentType }>) => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const Stub = (props: any) => {
      // Expose isOpen so we can assert modal visibility
      if (props.isOpen === false) return null;
      return <div data-testid="dynamic-modal" />;
    };
    Stub.displayName = "DynamicStub";
    return Stub;
  };
});

// Mock CSRF client
jest.mock("@/lib/csrf-client", () => ({
  fetchWithCSRF: jest.fn(),
}));

// ---- helpers ---------------------------------------------------------------

const tomorrow = new Date(Date.now() + 86400000).toISOString();

const sampleBookings = [
  {
    id: "b1",
    customerName: "Sara Ali",
    customerPhone: "+974 5555 1234",
    customerEmail: "sara@test.com",
    service: "Consultation",
    appointmentDate: tomorrow,
    appointmentTime: "10:00",
    duration: 30,
    status: "pending",
    depositAmount: 50,
    depositPaid: false,
  },
  {
    id: "b2",
    customerName: "Ahmad Khan",
    customerPhone: "+974 5555 5678",
    customerEmail: null,
    service: "Follow-up",
    appointmentDate: tomorrow,
    appointmentTime: "14:00",
    duration: 15,
    status: "confirmed",
    depositAmount: null,
    depositPaid: false,
  },
];

function setupFetchMock(integrations: unknown[] = []) {
  (global.fetch as jest.Mock).mockImplementation((url: string) => {
    if (url.includes("/api/integrations")) {
      return Promise.resolve({
        ok: true,
        json: () => Promise.resolve({ integrations }),
      });
    }
    return Promise.resolve({
      ok: true,
      json: () => Promise.resolve({ success: true }),
    });
  });
}

// ---- tests -----------------------------------------------------------------

describe("AppointmentsList", () => {
  const onRefresh = jest.fn().mockResolvedValue(undefined);

  beforeEach(() => {
    jest.clearAllMocks();
    jest.useFakeTimers({ advanceTimers: true });
    setupFetchMock();
  });

  afterEach(() => {
    jest.useRealTimers();
    jest.restoreAllMocks();
  });

  // ---------- empty state ---------------------------------------------------

  describe("empty state", () => {
    it("shows empty message when there are no bookings", async () => {
      render(
        <AppointmentsList lang="en" bookings={[]} onRefresh={onRefresh} />,
      );

      await waitFor(() => {
        expect(
          screen.getByText("No appointments scheduled"),
        ).toBeInTheDocument();
      });
    });

    it("shows the create booking button in empty state", async () => {
      render(
        <AppointmentsList lang="en" bookings={[]} onRefresh={onRefresh} />,
      );

      await waitFor(() => {
        const buttons = screen.getAllByText("Create appointment");
        expect(buttons.length).toBeGreaterThanOrEqual(1);
      });
    });
  });

  // ---------- rendering bookings --------------------------------------------

  describe("rendering bookings", () => {
    it("renders customer names for provided bookings", async () => {
      render(
        <AppointmentsList
          lang="en"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      await waitFor(() => {
        expect(screen.getByText("Sara Ali")).toBeInTheDocument();
        expect(screen.getByText("Ahmad Khan")).toBeInTheDocument();
      });
    });

    it("renders service names", async () => {
      render(
        <AppointmentsList
          lang="en"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      await waitFor(() => {
        expect(screen.getByText("Consultation")).toBeInTheDocument();
        expect(screen.getByText("Follow-up")).toBeInTheDocument();
      });
    });

    it("renders status badges", async () => {
      render(
        <AppointmentsList
          lang="en"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      await waitFor(() => {
        // Status text also appears in the filter dropdown, so use getAllByText
        const pendingElements = screen.getAllByText("Pending");
        expect(pendingElements.length).toBeGreaterThanOrEqual(2); // filter option + badge
        const confirmedElements = screen.getAllByText("Confirmed");
        expect(confirmedElements.length).toBeGreaterThanOrEqual(2); // filter option + badge
      });
    });

    it("shows View details buttons for each booking", async () => {
      render(
        <AppointmentsList
          lang="en"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      await waitFor(() => {
        const buttons = screen.getAllByText("View details");
        expect(buttons).toHaveLength(2);
      });
    });
  });

  // ---------- Arabic --------------------------------------------------------

  describe("Arabic language", () => {
    it("uses Arabic strings when lang=ar", async () => {
      render(
        <AppointmentsList lang="ar" bookings={[]} onRefresh={onRefresh} />,
      );

      await waitFor(() => {
        expect(screen.getByText("لا توجد مواعيد مجدولة")).toBeInTheDocument();
      });
    });

    it("shows Arabic header text", async () => {
      render(
        <AppointmentsList
          lang="ar"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      await waitFor(() => {
        const elements = screen.getAllByText("المواعيد");
        expect(elements.length).toBeGreaterThanOrEqual(1);
      });
    });
  });

  // ---------- header actions ------------------------------------------------

  describe("header actions", () => {
    it("shows the Appointments heading", () => {
      render(
        <AppointmentsList
          lang="en"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      const elements = screen.getAllByText("Appointments");
      expect(elements.length).toBeGreaterThanOrEqual(1);
    });

    it("shows Manage Services button", () => {
      render(
        <AppointmentsList
          lang="en"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      expect(screen.getByText("Manage Services")).toBeInTheDocument();
    });

    it("shows Connect Calendar button", () => {
      render(
        <AppointmentsList
          lang="en"
          bookings={sampleBookings}
          onRefresh={onRefresh}
        />,
      );

      expect(screen.getByText("Connect Calendar")).toBeInTheDocument();
    });
  });
});
