import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, waitFor, within } from "@testing-library/react";
import { PetProfileCard } from "../components/PetProfileCard.js";

const FULL_SUMMARY = {
  id: "pet-1",
  name: "Buddy",
  breed: "Golden Retriever",
  dateOfBirth: "2022-03-15",
  weightKg: 30.5,
  coatType: "double",
  temperamentScore: 4,
  temperamentFlags: ["anxious", "friendly"],
  medicalAlerts: [
    { id: "a1", type: "allergy", description: "Chicken allergy", severity: "high" },
    { id: "a2", type: "condition", description: "Hip dysplasia", severity: "medium" },
  ],
  preferredCuts: ["teddy bear", "puppy cut"],
  recentVisits: [
    { id: "v1", petId: "pet-1", appointmentId: "appt-1", staffId: "staff-1", cutStyle: "teddy bear", productsUsed: "oat shampoo", notes: "Good boy", groomedAt: "2025-05-01T10:00:00Z", createdAt: "2025-05-01T10:00:00Z" },
    { id: "v2", petId: "pet-1", appointmentId: "appt-2", staffId: "staff-2", cutStyle: "puppy cut", productsUsed: null, notes: null, groomedAt: "2025-04-01T10:00:00Z", createdAt: "2025-04-01T10:00:00Z" },
  ],
  nextAppointment: { id: "appt-3", startTime: "2025-06-01T09:00:00Z", serviceName: "Full groom" },
};

const EMPTY_SUMMARY = {
  id: "pet-2",
  name: "Whiskers",
  breed: null,
  dateOfBirth: null,
  weightKg: null,
  coatType: null,
  temperamentScore: null,
  temperamentFlags: [],
  medicalAlerts: [],
  preferredCuts: [],
  recentVisits: [],
  nextAppointment: null,
};

beforeEach(() => {
  vi.restoreAllMocks();
});

describe("PetProfileCard", () => {
  it("shows loading skeleton while fetching", () => {
    global.fetch = vi.fn(() => new Promise(() => {})) as unknown as typeof fetch;
    render(<PetProfileCard petId="pet-1" />);
    expect(screen.getByText(/loading/i)).toBeInTheDocument();
  });

  it("renders full profile data correctly", async () => {
    global.fetch = vi.fn(() =>
      Promise.resolve({
        ok: true,
        status: 200,
        json: async () => FULL_SUMMARY,
      } as Response)
    ) as unknown as typeof fetch;

    render(<PetProfileCard petId="pet-1" />);

    await waitFor(() => {
      expect(screen.getByText("Buddy")).toBeInTheDocument();
    });
    expect(screen.getByText("Golden Retriever")).toBeInTheDocument();
    // age computed from DOB
    expect(screen.getByText(/yr/)).toBeInTheDocument();
    // weight
    expect(screen.getByText(/30.5 kg/)).toBeInTheDocument();
    // coat type badge
    expect(screen.getByText("double")).toBeInTheDocument();
    // medical alerts
    expect(screen.getByText("Chicken allergy")).toBeInTheDocument();
    expect(screen.getByText("Hip dysplasia")).toBeInTheDocument();
    // preferred cuts
    expect(screen.getByText("teddy bear")).toBeInTheDocument();
  });

  it("displays severity-colored badges for medical alerts", async () => {
    global.fetch = vi.fn(() =>
      Promise.resolve({
        ok: true,
        status: 200,
        json: async () => FULL_SUMMARY,
      } as Response)
    ) as unknown as typeof fetch;

    render(<PetProfileCard petId="pet-1" />);

    await waitFor(() => {
      expect(screen.getByText("Chicken allergy")).toBeInTheDocument();
    });

    const highAlert = screen.getByText("Chicken allergy").closest("span");
    expect(highAlert).toHaveStyle({ color: "#dc2626" }); // high = red

    const mediumAlert = screen.getByText("Hip dysplasia").closest("span");
    expect(mediumAlert).toHaveStyle({ color: "#d97706" }); // medium = amber
  });

  it("handles empty pet data gracefully", async () => {
    global.fetch = vi.fn(() =>
      Promise.resolve({
        ok: true,
        status: 200,
        json: async () => EMPTY_SUMMARY,
      } as Response)
    ) as unknown as typeof fetch;

    render(<PetProfileCard petId="pet-2" />);

    await waitFor(() => {
      expect(screen.getByText("Whiskers")).toBeInTheDocument();
    });
    // no section labels with no data
    expect(screen.queryByText(/medical alerts/i)).not.toBeInTheDocument();
    expect(screen.queryByText(/preferred cuts/i)).not.toBeInTheDocument();
    expect(screen.queryByText(/recent visits/i)).not.toBeInTheDocument();
  });

  it("shows error message on fetch failure", async () => {
    global.fetch = vi.fn(() => Promise.reject(new Error("network error"))) as unknown as typeof fetch;

    render(<PetProfileCard petId="pet-1" />);

    await waitFor(() => {
      expect(screen.getByText(/failed to load/i)).toBeInTheDocument();
    });
  });

  it("refetches when petId changes", async () => {
    const fetchMock = vi.fn((url: string) => {
      if ((url as string).includes("pet-1")) {
        return Promise.resolve({
          ok: true,
          status: 200,
          json: async () => ({ ...FULL_SUMMARY, name: "Buddy" }),
        } as Response);
      }
      return Promise.resolve({
        ok: true,
        status: 200,
        json: async () => ({ ...EMPTY_SUMMARY, name: "Whiskers" }),
      } as Response);
    }) as unknown as typeof fetch;
    global.fetch = fetchMock;

    const { rerender } = render(<PetProfileCard petId="pet-1" />);
    await waitFor(() => expect(screen.getByText("Buddy")).toBeInTheDocument());
    expect(fetchMock).toHaveBeenCalledWith("/api/pets/pet-1/profile-summary");

    rerender(<PetProfileCard petId="pet-2" />);
    await waitFor(() => expect(screen.getByText("Whiskers")).toBeInTheDocument());
    expect(fetchMock).toHaveBeenCalledWith("/api/pets/pet-2/profile-summary");
  });
});
