// ABOUTME: Tests for OnboardingBanner component that prompts new users to complete setup.
// ABOUTME: Covers Garmin connection, period date, and notification time banners.

import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { OnboardingBanner, type OnboardingStatus } from "./onboarding-banner";

// Mock next/link
vi.mock("next/link", () => ({
  default: ({
    children,
    href,
  }: {
    children: React.ReactNode;
    href: string;
  }) => <a href={href}>{children}</a>,
}));

describe("OnboardingBanner", () => {
  const defaultStatus: OnboardingStatus = {
    garminConnected: true,
    lastPeriodDate: "2024-01-15",
    notificationTime: "07:00",
  };

  describe("rendering conditions", () => {
    it("renders nothing when all setup is complete", () => {
      const { container } = render(<OnboardingBanner status={defaultStatus} />);
      expect(container.firstChild).toBeNull();
    });

    it("renders Garmin banner when not connected", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, garminConnected: false }}
        />,
      );
      expect(
        screen.getByText(/Connect your Garmin to get started/i),
      ).toBeInTheDocument();
    });

    it("renders period banner when lastPeriodDate is null", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, lastPeriodDate: null }}
        />,
      );
      expect(
        screen.getByText(/Set your last period date for accurate tracking/i),
      ).toBeInTheDocument();
    });

    it("renders period banner when lastPeriodDate is empty string", () => {
      render(
        <OnboardingBanner status={{ ...defaultStatus, lastPeriodDate: "" }} />,
      );
      expect(
        screen.getByText(/Set your last period date for accurate tracking/i),
      ).toBeInTheDocument();
    });

    it("renders notification banner when notificationTime is missing", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, notificationTime: "" }}
        />,
      );
      expect(
        screen.getByText(/Set your preferred notification time/i),
      ).toBeInTheDocument();
    });

    it("renders multiple banners when multiple items are missing", () => {
      render(
        <OnboardingBanner
          status={{
            garminConnected: false,
            lastPeriodDate: null,
            notificationTime: "",
          }}
        />,
      );
      expect(
        screen.getByText(/Connect your Garmin to get started/i),
      ).toBeInTheDocument();
      expect(
        screen.getByText(/Set your last period date for accurate tracking/i),
      ).toBeInTheDocument();
      expect(
        screen.getByText(/Set your preferred notification time/i),
      ).toBeInTheDocument();
    });
  });

  describe("Garmin banner", () => {
    it("links to /settings/garmin", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, garminConnected: false }}
        />,
      );
      const link = screen.getByRole("link", { name: /Connect/i });
      expect(link).toHaveAttribute("href", "/settings/garmin");
    });

    it("has proper accessibility attributes", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, garminConnected: false }}
        />,
      );
      const banner = screen.getByRole("alert");
      expect(banner).toBeInTheDocument();
    });
  });

  describe("period date banner", () => {
    it("calls onSetPeriodDate callback when button is clicked", () => {
      const onSetPeriodDate = vi.fn();
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, lastPeriodDate: null }}
          onSetPeriodDate={onSetPeriodDate}
        />,
      );
      const button = screen.getByRole("button", { name: /Set date/i });
      fireEvent.click(button);
      expect(onSetPeriodDate).toHaveBeenCalledTimes(1);
    });

    it("shows 'Set date' button for period banner", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, lastPeriodDate: null }}
        />,
      );
      expect(
        screen.getByRole("button", { name: /Set date/i }),
      ).toBeInTheDocument();
    });
  });

  describe("notification time banner", () => {
    it("links to /settings", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, notificationTime: "" }}
        />,
      );
      const link = screen.getByRole("link", { name: /Configure/i });
      expect(link).toHaveAttribute("href", "/settings");
    });
  });

  describe("styling", () => {
    it("uses alert styling with appropriate colors", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, garminConnected: false }}
        />,
      );
      const banner = screen.getByRole("alert");
      expect(banner.className).toContain("border");
      expect(banner.className).toContain("rounded");
    });

    it("has proper spacing between multiple banners", () => {
      const { container } = render(
        <OnboardingBanner
          status={{
            garminConnected: false,
            lastPeriodDate: null,
            notificationTime: "",
          }}
        />,
      );
      const wrapper = container.firstChild as HTMLElement;
      expect(wrapper.className).toContain("space-y");
    });
  });

  describe("icons", () => {
    it("shows watch icon for Garmin banner", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, garminConnected: false }}
        />,
      );
      expect(screen.getByText("⌚")).toBeInTheDocument();
    });

    it("shows calendar icon for period banner", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, lastPeriodDate: null }}
        />,
      );
      expect(screen.getByText("📅")).toBeInTheDocument();
    });

    it("shows bell icon for notification banner", () => {
      render(
        <OnboardingBanner
          status={{ ...defaultStatus, notificationTime: "" }}
        />,
      );
      expect(screen.getByText("🔔")).toBeInTheDocument();
    });
  });
});
