import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { jest } from "@jest/globals";

// Mock MainContainer
jest.unstable_mockModule("./components/MainContainer.js", () => ({
  __esModule: true,
  default: () => <div data-testid="main-container">Main Container</div>,
}));

// Mock MSAL
const mockLogoutRedirect = jest.fn();
jest.unstable_mockModule("@azure/msal-react", () => ({
  __esModule: true,
  useMsal: () => ({
    instance: {
      logoutRedirect: mockLogoutRedirect,
    },
    accounts: [],
  }),
}));

// Mock useTokenExpiryMonitor
const mockHandleRenew = jest.fn();
const mockHandleExpire = jest.fn();
let mockShowDialog = false;
let mockCountdown = 60;

jest.unstable_mockModule("./hooks/useTokenExpiryMonitor.js", () => ({
  __esModule: true,
  useTokenExpiryMonitor: ({ onRenew, onExpire }) => ({
    showDialog: mockShowDialog,
    countdown: mockCountdown,
    handleRenew: () => {
      mockHandleRenew();
      if (onRenew) onRenew();
    },
    handleExpire: () => {
      mockHandleExpire();
      if (onExpire) onExpire();
    },
  }),
}));

// Mock apiService
jest.unstable_mockModule("./services/apiService.js", () => ({
  __esModule: true,
  default: () => ({
    postApi: jest.fn(),
    getApi: jest.fn(),
    RoleChangedPopupElement: <div data-testid="role-changed-popup" />,
  }),
}));

// Import after mocks
const { default: App } = await import("./App.js");

describe("App Component", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockShowDialog = false;
    mockCountdown = 60;
  });

  it("renders MainContainer", () => {
    render(<App />);
    expect(screen.getByTestId("main-container")).toBeInTheDocument();
  });

  it("renders RoleChangedPopupElement", () => {
    render(<App />);
    expect(screen.getByTestId("role-changed-popup")).toBeInTheDocument();
  });

  it("does not show dialog when showDialog is false", () => {
    mockShowDialog = false;
    render(<App />);
    expect(screen.queryByText("Session Expiring")).not.toBeInTheDocument();
  });
});

describe("App Component with Dialog", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockShowDialog = true;
    mockCountdown = 60;
  });

  it("shows dialog when showDialog is true", () => {
    render(<App />);
    expect(screen.getByText("Session Expiring")).toBeInTheDocument();
  });

  it("displays session expiring message", () => {
    render(<App />);
    expect(screen.getByText(/Your session is about to expire/i)).toBeInTheDocument();
  });

  it("displays formatted countdown", () => {
    mockCountdown = 65;
    render(<App />);
    expect(screen.getByText(/01:05/)).toBeInTheDocument();
  });

  it("renders Yes, Extend button", () => {
    render(<App />);
    expect(screen.getByRole("button", { name: /Yes, Extend/i })).toBeInTheDocument();
  });

  it("renders No, Logout button", () => {
    render(<App />);
    expect(screen.getByRole("button", { name: /No, Logout/i })).toBeInTheDocument();
  });

  it("calls handleRenew when Yes, Extend is clicked", () => {
    render(<App />);
    const extendButton = screen.getByRole("button", { name: /Yes, Extend/i });
    fireEvent.click(extendButton);
    expect(mockHandleRenew).toHaveBeenCalled();
  });

  it("calls handleExpire when No, Logout is clicked", () => {
    render(<App />);
    const logoutButton = screen.getByRole("button", { name: /No, Logout/i });
    fireEvent.click(logoutButton);
    expect(mockHandleExpire).toHaveBeenCalled();
  });

  it("formats countdown with leading zeros", () => {
    mockCountdown = 9;
    render(<App />);
    expect(screen.getByText(/00:09/)).toBeInTheDocument();
  });

  it("formats countdown for full minutes", () => {
    mockCountdown = 120;
    render(<App />);
    expect(screen.getByText(/02:00/)).toBeInTheDocument();
  });
});

describe("App formatCountdown function", () => {
  beforeEach(() => {
    mockShowDialog = true;
  });

  it("formats 0 seconds correctly", () => {
    mockCountdown = 0;
    render(<App />);
    expect(screen.getByText(/00:00/)).toBeInTheDocument();
  });

  it("formats 59 seconds correctly", () => {
    mockCountdown = 59;
    render(<App />);
    expect(screen.getByText(/00:59/)).toBeInTheDocument();
  });

  it("formats 60 seconds correctly", () => {
    mockCountdown = 60;
    render(<App />);
    expect(screen.getByText(/01:00/)).toBeInTheDocument();
  });

  it("formats 90 seconds correctly", () => {
    mockCountdown = 90;
    render(<App />);
    expect(screen.getByText(/01:30/)).toBeInTheDocument();
  });
});
