import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import AppointmentTypesManager from "@/app/[lang]/dashboard/components/AppointmentTypesManager";
import { fetchWithCSRF } from "@/lib/csrf-client";

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

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

const sampleTypes = [
  {
    id: "t1",
    nameEn: "Consultation",
    nameAr: "استشارة",
    duration: 30,
    price: 150,
    isActive: true,
    sortOrder: 0,
  },
  {
    id: "t2",
    nameEn: "Follow-up",
    nameAr: "متابعة",
    duration: 15,
    price: null,
    isActive: true,
    sortOrder: 1,
  },
];

function mockFetchTypes(types: typeof sampleTypes = sampleTypes) {
  (global.fetch as jest.Mock).mockImplementation((url: string) => {
    if (url.includes("appointment-types")) {
      return Promise.resolve({
        ok: true,
        json: () => Promise.resolve({ types }),
      });
    }
    return Promise.resolve({
      ok: true,
      json: () => Promise.resolve({ success: true }),
    });
  });
}

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

describe("AppointmentTypesManager", () => {
  const onClose = jest.fn();

  beforeEach(() => {
    jest.clearAllMocks();
    mockFetchTypes();
  });

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

  // ---------- closed state --------------------------------------------------

  describe("when isOpen is false", () => {
    it("renders nothing", () => {
      const { container } = render(
        <AppointmentTypesManager lang="en" isOpen={false} onClose={onClose} />,
      );

      expect(container.firstChild).toBeNull();
    });
  });

  // ---------- loads and displays types --------------------------------------

  describe("when isOpen is true", () => {
    it("shows the Service Types heading", async () => {
      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(screen.getByText("Service Types")).toBeInTheDocument();
      });
    });

    it("displays loaded service type names", async () => {
      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

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

    it("displays Arabic names for each type", async () => {
      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(screen.getByText("استشارة")).toBeInTheDocument();
        expect(screen.getByText("متابعة")).toBeInTheDocument();
      });
    });

    it("shows the count badge", async () => {
      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(screen.getByText("2")).toBeInTheDocument();
      });
    });
  });

  // ---------- Add button ----------------------------------------------------

  describe("Add button", () => {
    it("has an Add button", async () => {
      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(screen.getByText("Add")).toBeInTheDocument();
      });
    });

    it("shows form when Add is clicked", async () => {
      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

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

      fireEvent.click(screen.getByText("Add"));

      expect(screen.getByText("Add New Service Type")).toBeInTheDocument();
    });
  });

  // ---------- Delete --------------------------------------------------------

  describe("delete", () => {
    it("calls fetchWithCSRF with DELETE method when delete button is clicked", async () => {
      (fetchWithCSRF as jest.Mock).mockResolvedValue({
        ok: true,
        json: () => Promise.resolve({ success: true }),
      });

      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      // Wait for types to load
      await waitFor(() => {
        expect(screen.getByText("Consultation")).toBeInTheDocument();
      });

      // Find delete buttons by title attribute
      const deleteButtons = screen.getAllByTitle("Delete");
      expect(deleteButtons.length).toBe(2);

      // Click first delete
      fireEvent.click(deleteButtons[0]);

      await waitFor(() => {
        expect(fetchWithCSRF).toHaveBeenCalledWith(
          "/api/dashboard/appointment-types/t1",
          { method: "DELETE" },
        );
      });
    });
  });

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

  describe("empty state", () => {
    it("shows empty message when no types exist", async () => {
      mockFetchTypes([]);

      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(
          screen.getByText("No service types configured"),
        ).toBeInTheDocument();
      });
    });

    it("shows Add Service button in empty state", async () => {
      mockFetchTypes([]);

      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(screen.getByText("Add Service")).toBeInTheDocument();
      });
    });
  });

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

  describe("Arabic language", () => {
    it("shows Arabic heading when lang=ar", async () => {
      render(
        <AppointmentTypesManager lang="ar" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(screen.getByText("أنواع الخدمات")).toBeInTheDocument();
      });
    });

    it("shows Arabic empty state when lang=ar", async () => {
      mockFetchTypes([]);

      render(
        <AppointmentTypesManager lang="ar" isOpen={true} onClose={onClose} />,
      );

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

  // ---------- close ---------------------------------------------------------

  describe("close button", () => {
    it("calls onClose when the X button is clicked", async () => {
      render(
        <AppointmentTypesManager lang="en" isOpen={true} onClose={onClose} />,
      );

      await waitFor(() => {
        expect(screen.getByText("Service Types")).toBeInTheDocument();
      });

      // The close button is an X icon button in the header; find by its role/area
      // In this component there's an <X> icon button at the end of the header
      // We can use getAllByRole and filter
      const buttons = screen.getAllByRole("button");
      // The close button is the last button in the header row
      // We'll find it by looking for buttons that don't have text content
      const closeBtn = buttons.find(
        (btn) => btn.querySelector("svg") && btn.textContent?.trim() === "",
      );

      if (closeBtn) {
        fireEvent.click(closeBtn);
        expect(onClose).toHaveBeenCalledTimes(1);
      }
    });
  });
});
