import { describe, expect, it, vi } from "vitest";
import { fireEvent, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import ScooterCard, { type Scooter } from "@/components/scooters/ScooterCard";

function buildScooter(overrides: Partial<Scooter> = {}): Scooter {
  return {
    id: 1,
    code: "SC-001",
    model: "Xiaomi Pro",
    status: "active",
    status_label: "نشطة",
    battery_percent: 75,
    image: null,
    location: "الرياض",
    rides_today: 5,
    revenue_today: 200,
    your_share_today: 50,
    currency: "SAR",
    ...overrides,
  };
}

describe("ScooterCard", () => {
  it("renders as a static card when onClick is not provided", () => {
    render(<ScooterCard scooter={buildScooter()} />);

    expect(screen.getByText("SC-001")).toBeInTheDocument();
    expect(screen.queryByRole("button")).not.toBeInTheDocument();
  });

  it("renders as a button and invokes onClick when supplied", async () => {
    const onClick = vi.fn();
    const user = userEvent.setup();

    render(<ScooterCard scooter={buildScooter()} onClick={onClick} />);

    const cardButton = screen.getByRole("button");
    expect(cardButton).toHaveAttribute("type", "button");
    await user.click(cardButton);
    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it("renders scooter identity, share, rides, and location", () => {
    render(
      <ScooterCard
        scooter={buildScooter({
          code: "SC-042",
          model: "Segway Max",
          your_share_today: 1200,
          rides_today: 8,
          location: "جدة",
        })}
      />,
    );

    expect(screen.getByText("SC-042")).toBeInTheDocument();
    expect(screen.getByText("Segway Max")).toBeInTheDocument();
    expect(screen.getByText(/1,200 ريال حصتك/)).toBeInTheDocument();
    expect(screen.getByText("8 رحلة اليوم")).toBeInTheDocument();
    expect(screen.getByText("جدة")).toBeInTheDocument();
  });

  it.each([
    ["active", "نشطة", "text-[#FCD704]"],
    ["maintenance", "صيانة", "text-orange-400"],
    ["in_ride", "في رحلة", "text-blue-400"],
    ["inactive", "غير نشطة", "text-gray-400"],
    ["out_of_service", "خارج الخدمة", "text-gray-400"],
  ] as const)(
    "renders the %s status label with its visual variant",
    (status, statusLabel, expectedClass) => {
      render(
        <ScooterCard
          scooter={buildScooter({ status, status_label: statusLabel })}
        />,
      );

      const badge = screen.getByText(`● ${statusLabel}`);
      expect(badge.className).toContain(expectedClass);
    },
  );

  it.each([
    [60, "bg-[#FCD704]"],
    [30, "bg-yellow-400"],
    [10, "bg-red-500"],
    [0, "bg-red-500"],
  ] as const)(
    "renders the battery bar for %s percent charge",
    (batteryPercent, expectedClass) => {
      render(
        <ScooterCard
          scooter={buildScooter({ battery_percent: batteryPercent })}
        />,
      );

      expect(screen.getByText(`${batteryPercent}% ⚡`)).toBeInTheDocument();
      const batteryLabel = screen.getByText("البطارية");
      const batteryTrack = batteryLabel.parentElement?.nextElementSibling;
      const batteryBar = batteryTrack?.querySelector(".h-full.rounded-full");
      expect(batteryBar?.className).toContain(expectedClass);
      expect(batteryBar).toHaveStyle({ width: `${batteryPercent}%` });
    },
  );

  it("shows the fallback icon when no image is provided", () => {
    render(<ScooterCard scooter={buildScooter({ image: null })} />);

    expect(screen.queryByRole("img")).not.toBeInTheDocument();
    const fallbackIcon = document.querySelector(".ri-e-bike-line");
    expect(fallbackIcon).toBeInTheDocument();
    expect(fallbackIcon?.parentElement).toHaveStyle({ display: "flex" });
  });

  it("shows the image and hides the fallback when an image URL is provided", () => {
    render(
      <ScooterCard
        scooter={buildScooter({ image: "https://example.com/scooter.jpg" })}
      />,
    );

    const image = screen.getByRole("img", { name: "SC-001" });
    expect(image).toHaveAttribute("src", "https://example.com/scooter.jpg");
    const fallback = image.nextElementSibling as HTMLElement;
    expect(fallback.style.display).toBe("none");
  });

  it("reveals the fallback icon when the image fails to load", () => {
    render(
      <ScooterCard
        scooter={buildScooter({ image: "https://example.com/broken.jpg" })}
      />,
    );

    const image = screen.getByRole("img", { name: "SC-001" });
    fireEvent.error(image);

    expect(image.style.display).toBe("none");
    const fallback = image.nextElementSibling as HTMLElement;
    expect(fallback.style.display).toBe("flex");
    expect(fallback.querySelector(".ri-e-bike-line")).toBeInTheDocument();
  });

  it("hides the image without throwing when the fallback sibling is missing", () => {
    render(
      <ScooterCard
        scooter={buildScooter({ image: "https://example.com/broken.jpg" })}
      />,
    );

    const image = screen.getByRole("img", { name: "SC-001" });
    image.nextElementSibling?.remove();
    fireEvent.error(image);

    expect(image.style.display).toBe("none");
  });
});
