import { beforeEach, describe, expect, it, vi } from "vitest";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { SportIconUploader } from "../SportIconUploader";
import type { FormEvent } from "react";

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

describe("SportIconUploader", () => {
  it("stores the initial icon URL in a hidden input", () => {
    const { container } = render(
      <SportIconUploader uploadUrl="/api/upload-sport-icon" initialIconUrl="nfl.svg" sportName="NFL" />
    );

    expect(container.querySelector('input[name="iconUrl"]')).toHaveValue("nfl.svg");
    expect(screen.getByText("Current icon")).toBeInTheDocument();
  });

  it("rejects non-SVG files before upload", async () => {
    const { container } = render(<SportIconUploader uploadUrl="/api/upload-sport-icon" />);
    const fileInput = container.querySelector('input[type="file"]') as HTMLInputElement;

    fireEvent.change(fileInput, {
      target: { files: [new File(["not svg"], "icon.png", { type: "image/png" })] },
    });

    expect(await screen.findByText("Choose an SVG file.")).toBeInTheDocument();
  });

  it("chooses an icon from an existing sport", () => {
    const { container } = render(
      <SportIconUploader
        uploadUrl="/api/upload-sport-icon"
        existingIconOptions={[
          { id: "sport-1", name: "NFL", iconUrl: "nfl.svg" },
          { id: "sport-2", name: "NBA", iconUrl: "nba.svg" },
        ]}
      />
    );

    fireEvent.change(screen.getByRole("combobox", { name: "Use an existing sport icon" }), {
      target: { value: "nba.svg" },
    });

    expect(container.querySelector('input[name="iconUrl"]')).toHaveValue("nba.svg");
    expect(screen.getByText("Current icon")).toBeInTheDocument();
  });

  it("uploads an SVG and updates the hidden input", async () => {
    vi.stubGlobal(
      "fetch",
      vi.fn().mockResolvedValue({
        ok: true,
        json: async () => ({ iconUrl: "https://res.cloudinary.com/demo/image/upload/v1/sports-icons/nfl.svg" }),
      })
    );

    const { container } = render(<SportIconUploader uploadUrl="/api/upload-sport-icon" />);
    const fileInput = container.querySelector('input[type="file"]') as HTMLInputElement;

    fireEvent.change(fileInput, {
      target: { files: [new File(["<svg />"], "icon.svg", { type: "image/svg+xml" })] },
    });

    fireEvent.click(await screen.findByRole("button", { name: "Upload SVG" }));

    await waitFor(() => {
      expect(container.querySelector('input[name="iconUrl"]')).toHaveValue(
        "https://res.cloudinary.com/demo/image/upload/v1/sports-icons/nfl.svg"
      );
    });
    expect(screen.getByText("Icon uploaded. Save the sport to apply it.")).toBeInTheDocument();
  });

  it("does not submit a parent form when uploading an SVG", async () => {
    vi.stubGlobal(
      "fetch",
      vi.fn().mockResolvedValue({
        ok: true,
        json: async () => ({ iconUrl: "https://res.cloudinary.com/demo/image/upload/v1/sports-icons/nfl.svg" }),
      })
    );
    const onSubmit = vi.fn((event: FormEvent<HTMLFormElement>) => event.preventDefault());

    const { container } = render(
      <form onSubmit={onSubmit}>
        <SportIconUploader uploadUrl="/api/upload-sport-icon" />
      </form>
    );
    const fileInput = container.querySelector('input[type="file"]') as HTMLInputElement;

    fireEvent.change(fileInput, {
      target: { files: [new File(["<svg />"], "icon.svg", { type: "image/svg+xml" })] },
    });
    fireEvent.click(await screen.findByRole("button", { name: "Upload SVG" }));

    await waitFor(() => expect(global.fetch).toHaveBeenCalled());
    expect(onSubmit).not.toHaveBeenCalled();
  });
});
