import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import { PetForm } from "../portal/sections/PetForm.js";
import type { Pet } from "@groombook/types";

const BASE_PET: Pet = {
  id: "pet-1",
  clientId: "client-1",
  name: "Buddy",
  species: "dog",
  breed: "Labrador",
  weightKg: 25,
  dateOfBirth: "2020-03-15T00:00:00.000Z",
  healthAlerts: null,
  groomingNotes: null,
  cutStyle: null,
  shampooPreference: null,
  specialCareNotes: null,
  customFields: {},
  coatType: null,
  preferredCuts: [],
  medicalAlerts: [],
  createdAt: "2024-01-01T00:00:00.000Z",
  updatedAt: "2024-01-01T00:00:00.000Z",
};

describe("PetForm", () => {
  const onSave = vi.fn();
  const onCancel = vi.fn();

  beforeEach(() => {
    onSave.mockClear();
    onCancel.mockClear();
  });

  // ── Coat type ───────────────────────────────────────────────────────────────

  it("allows coat type selection from dropdown", () => {
    render(<PetForm pet={BASE_PET} onSave={onSave} onCancel={onCancel} />);
    const select = screen.getByRole("combobox", { name: /coat type/i });
    fireEvent.change(select, { target: { value: "curly" } });
    expect((select as HTMLSelectElement).value).toBe("curly");
  });

  it("persists coat type on save", () => {
    render(<PetForm pet={BASE_PET} onSave={onSave} onCancel={onCancel} />);
    fireEvent.change(screen.getByRole("combobox", { name: /coat type/i }), { target: { value: "double" } });
    fireEvent.click(screen.getByRole("button", { name: /save/i }));
    expect(onSave).toHaveBeenCalledWith(
      expect.objectContaining({ coatType: "double" })
    );
  });

  // ── Preferred cuts tag input ────────────────────────────────────────────────

  it("adds a cut when Enter is pressed", () => {
    render(<PetForm pet={BASE_PET} onSave={onSave} onCancel={onCancel} />);
    const input = screen.getByPlaceholderText(/type a cut name/i);
    fireEvent.change(input, { target: { value: "Puppy Cut" } });
    fireEvent.keyDown(input, { key: "Enter" });
    expect(screen.getByText("Puppy Cut")).toBeTruthy();
  });

  it("adds a cut when the + button is clicked", () => {
    render(<PetForm pet={BASE_PET} onSave={onSave} onCancel={onCancel} />);
    const input = screen.getByPlaceholderText(/type a cut name/i);
    fireEvent.change(input, { target: { value: "Teddy Bear" } });
    fireEvent.click(screen.getByRole("button", { name: "Add" }));
    expect(screen.getByText("Teddy Bear")).toBeTruthy();
  });

  it("removes a cut when X is clicked", () => {
    const petWithCuts: Pet = {
      ...BASE_PET,
      preferredCuts: ["Puppy Cut", "Teddy Bear"],
    };
    render(<PetForm pet={petWithCuts} onSave={onSave} onCancel={onCancel} />);
    const puppyCutSpans = screen.getAllByText("Puppy Cut");
    const puppyCutTag = puppyCutSpans[0]?.closest("span");
    if (!puppyCutTag) return;
    const removeBtn = puppyCutTag.querySelector("button");
    if (!removeBtn) return;
    fireEvent.click(removeBtn);
    expect(screen.queryByText("Puppy Cut")).toBeNull();
    expect(screen.getByText("Teddy Bear")).toBeTruthy();
  });

  it("includes preferred cuts in save payload", () => {
    render(<PetForm pet={BASE_PET} onSave={onSave} onCancel={onCancel} />);
    fireEvent.change(screen.getByPlaceholderText(/type a cut name/i), { target: { value: "Puppy Cut" } });
    fireEvent.keyDown(screen.getByPlaceholderText(/type a cut name/i), { key: "Enter" });
    fireEvent.click(screen.getByRole("button", { name: /save/i }));
    expect(onSave).toHaveBeenCalledWith(
      expect.objectContaining({ preferredCuts: ["Puppy Cut"] })
    );
  });

  // ── Medical alerts ───────────────────────────────────────────────────────────

  it("adds a medical alert", () => {
    render(<PetForm pet={BASE_PET} onSave={onSave} onCancel={onCancel} />);
    fireEvent.click(screen.getByRole("button", { name: /add alert/i }));
    expect(screen.getByPlaceholderText(/alert type/i)).toBeTruthy();
  });

  it("removes a medical alert", () => {
    const petWithAlert: Pet = {
      ...BASE_PET,
      medicalAlerts: [{ id: "alert-1", type: "Allergic to chicken", description: "Causes hives", severity: "high" }],
    };
    render(<PetForm pet={petWithAlert} onSave={onSave} onCancel={onCancel} />);
    const removeButtons = screen.getAllByRole("button", { name: "" });
    if (removeButtons.length === 0) return;
    const removeButton = removeButtons[0]!;
    if (!removeButton) return;
    fireEvent.click(removeButton);
    expect(screen.queryByText("Allergic to chicken")).toBeNull();
  });

  it("validates alert type is non-empty", () => {
    render(<PetForm pet={BASE_PET} onSave={onSave} onCancel={onCancel} />);
    fireEvent.click(screen.getByRole("button", { name: /add alert/i }));
    fireEvent.click(screen.getByRole("button", { name: /save/i }));
    expect(screen.getByText(/type is required/i)).toBeTruthy();
    expect(onSave).not.toHaveBeenCalled();
  });

  it("shows medical alerts in save payload", () => {
    const petWithAlert: Pet = {
      ...BASE_PET,
      medicalAlerts: [{ id: "alert-1", type: "Sensitive skin", description: "Use hypoallergenic shampoo only", severity: "medium" }],
    };
    render(<PetForm pet={petWithAlert} onSave={onSave} onCancel={onCancel} />);
    fireEvent.click(screen.getByRole("button", { name: /save/i }));
    expect(onSave).toHaveBeenCalledWith(
      expect.objectContaining({
        medicalAlerts: expect.arrayContaining([
          expect.objectContaining({ type: "Sensitive skin", severity: "medium" }),
        ]),
      })
    );
  });

  // ── Temperament read-only display ─────────────────────────────────────────────

  it("displays temperament score as read-only stars", () => {
    const petWithTemperament: Pet = {
      ...BASE_PET,
      temperamentScore: 4,
      temperamentFlags: ["Anxious", "Good with kids"],
    };
    render(<PetForm pet={petWithTemperament} onSave={onSave} onCancel={onCancel} />);
    expect(screen.getByText("(4/5)")).toBeTruthy();
    expect(screen.getByText("Anxious")).toBeTruthy();
    expect(screen.getByText("Good with kids")).toBeTruthy();
  });
});