import React from "react";
import "@testing-library/jest-dom";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ToastProvider } from "./toast";
import { api } from "./api";
import EmailProviderConnections from "./components/EmailProviderConnections";

jest.mock("./api", () => ({
  api: {
    get: jest.fn(),
    post: jest.fn(),
    delete: jest.fn(),
    interceptors: { request: { use: jest.fn() }, response: { use: jest.fn() } },
  },
  getApiErrorMessage: (_err: unknown, fallback: string) => fallback,
}));

const mockedApi = api as jest.Mocked<typeof api>;

function renderComponent() {
  return render(
    <ToastProvider>
      <EmailProviderConnections />
    </ToastProvider>,
  );
}

describe("EmailProviderConnections", () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it("renders connected state for Gmail and Outlook, disconnected form for IMAP", async () => {
    mockedApi.get.mockImplementation((path: string) => {
      if (path === "/gmail/status") return Promise.resolve({ data: { connected: true, gmailAddress: "me@gmail.test" } });
      if (path === "/microsoft-graph/status") return Promise.resolve({ data: { connected: false } });
      if (path === "/imap/status") return Promise.resolve({ data: { connected: false } });
      return Promise.reject(new Error("unexpected path"));
    });

    renderComponent();

    expect(await screen.findByText("me@gmail.test")).toBeInTheDocument();
    expect(screen.getByLabelText("IMAP host")).toBeInTheDocument();
    expect(screen.getAllByText("Not connected").length).toBeGreaterThan(0);
  });

  it("submits IMAP connect form and reloads status on success", async () => {
    mockedApi.get.mockImplementation((path: string) => {
      if (path === "/gmail/status") return Promise.resolve({ data: { connected: false } });
      if (path === "/microsoft-graph/status") return Promise.resolve({ data: { connected: false } });
      if (path === "/imap/status") return Promise.resolve({ data: { connected: false } });
      return Promise.reject(new Error("unexpected path"));
    });
    mockedApi.post.mockResolvedValueOnce({ data: { username: "user@example.test" } });

    renderComponent();
    await screen.findByLabelText("IMAP host");

    await userEvent.type(screen.getByLabelText("IMAP host"), "imap.example.test");
    await userEvent.type(screen.getByLabelText("Username"), "user@example.test");
    await userEvent.type(screen.getByLabelText("Password"), "secret");
    await userEvent.click(screen.getByRole("button", { name: /connect imap account/i }));

    await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith("/imap/connect", expect.objectContaining({
      host: "imap.example.test",
      username: "user@example.test",
      password: "secret",
    })));
  });
});
