/**
 * Tests for the ServerStatusBar component.
 *
 * Covers loading state, online / offline rendering, and correct tooltip
 * wording that distinguishes the fail2ban daemon version from the BanGUI
 * application version.
 */

import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen } from "@testing-library/react";
import { FluentProvider, webLightTheme } from "@fluentui/react-components";
import { ServerStatusBar } from "../ServerStatusBar";

// ---------------------------------------------------------------------------
// Mock useServerStatus so tests never touch the network.
// ---------------------------------------------------------------------------

vi.mock("../../hooks/useServerStatus");

import { useServerStatus } from "../../hooks/useServerStatus";

const mockedUseServerStatus = vi.mocked(useServerStatus);

function renderBar(): void {
  render(
    <FluentProvider theme={webLightTheme}>
      <ServerStatusBar />
    </FluentProvider>,
  );
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe("ServerStatusBar", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("shows a spinner while the initial load is in progress", () => {
    mockedUseServerStatus.mockReturnValue({
      status: null,
      loading: true,
      error: null,
      refresh: vi.fn(),
    });
    renderBar();
    // The status-area spinner is labelled "Checking\u2026".
    expect(screen.getByText("Checking\u2026")).toBeInTheDocument();
  });

  it("renders an Online badge when the server is reachable", () => {
    mockedUseServerStatus.mockReturnValue({
      status: {
        online: true,
        version: "1.1.0",
        active_jails: 3,
        total_bans: 10,
        total_failures: 5,
      },
      loading: false,
      error: null,
      refresh: vi.fn(),
    });
    renderBar();
    expect(screen.getByText("Online")).toBeInTheDocument();
  });

  it("renders an Offline badge when the server is unreachable", () => {
    mockedUseServerStatus.mockReturnValue({
      status: {
        online: false,
        version: null,
        active_jails: 0,
        total_bans: 0,
        total_failures: 0,
      },
      loading: false,
      error: null,
      refresh: vi.fn(),
    });
    renderBar();
    expect(screen.getByText("Offline")).toBeInTheDocument();
  });

  it("displays the daemon version string when available", () => {
    mockedUseServerStatus.mockReturnValue({
      status: {
        online: true,
        version: "1.2.3",
        active_jails: 1,
        total_bans: 0,
        total_failures: 0,
      },
      loading: false,
      error: null,
      refresh: vi.fn(),
    });
    renderBar();
    expect(screen.getByText("v1.2.3")).toBeInTheDocument();
  });

  it("does not render a separate BanGUI version badge", () => {
    mockedUseServerStatus.mockReturnValue({
      status: {
        online: true,
        version: "1.2.3",
        active_jails: 1,
        total_bans: 0,
        total_failures: 0,
      },
      loading: false,
      error: null,
      refresh: vi.fn(),
    });
    renderBar();
    expect(screen.queryByText("BanGUI v9.9.9")).toBeNull();
  });

  it("does not render the version element when version is null", () => {
    mockedUseServerStatus.mockReturnValue({
      status: {
        online: false,
        version: null,
        active_jails: 0,
        total_bans: 0,
        total_failures: 0,
      },
      loading: false,
      error: null,
      refresh: vi.fn(),
    });
    renderBar();
    // No version string should appear in the document.
    expect(screen.queryByText(/^v\d/)).not.toBeInTheDocument();
  });

  it("shows jail / ban / failure counts when the server is online", () => {
    mockedUseServerStatus.mockReturnValue({
      status: {
        online: true,
        version: "1.0.0",
        active_jails: 4,
        total_bans: 21,
        total_failures: 99,
      },
      loading: false,
      error: null,
      refresh: vi.fn(),
    });
    renderBar();
    expect(screen.getByText("4")).toBeInTheDocument();
    expect(screen.getByText("21")).toBeInTheDocument();
    expect(screen.getByText("99")).toBeInTheDocument();
    // Verify the "Failed Attempts:" label (renamed from "Failures:").
    expect(screen.getByText("Failed Attempts:")).toBeInTheDocument();
  });

  it("renders an error message when the status fetch fails", () => {
    mockedUseServerStatus.mockReturnValue({
      status: null,
      loading: false,
      error: "Network error",
      refresh: vi.fn(),
    });
    renderBar();
    expect(screen.getByText("Network error")).toBeInTheDocument();
  });
});
