/* @vitest-environment jsdom */

import { fireEvent, render, screen, waitFor } from "@testing-library/react"
import { afterEach, describe, expect, it, vi } from "vitest"

import { MediaUploadForm } from "./media-upload-form"

describe("MediaUploadForm", () => {
  afterEach(() => {
    vi.restoreAllMocks()
  })

  it("updates accepted MIME list based on selected media type", () => {
    render(<MediaUploadForm />)

    const fileInput = screen.getByLabelText("File") as HTMLInputElement
    const typeSelect = screen.getByLabelText("Type") as HTMLSelectElement

    expect(fileInput.accept).toContain("image/jpeg")

    fireEvent.change(typeSelect, { target: { value: "video" } })

    expect(fileInput.accept).toContain("video/mp4")
    expect(fileInput.accept).not.toContain("image/jpeg")
  })

  it("shows API error message when upload fails", async () => {
    const fetchMock = vi.spyOn(globalThis, "fetch").mockResolvedValue({
      ok: false,
      json: async () => ({ message: "Invalid file type" }),
    } as Response)

    render(<MediaUploadForm />)

    const form = screen.getByRole("button", { name: "Upload media" }).closest("form")

    if (!form) {
      throw new Error("Upload form not found")
    }

    const fileInput = screen.getByLabelText("File") as HTMLInputElement
    fireEvent.change(fileInput, {
      target: {
        files: [new File(["x"], "demo.png", { type: "image/png" })],
      },
    })

    fireEvent.submit(form)

    await waitFor(() => {
      expect(screen.queryByText("Invalid file type")).not.toBeNull()
    })

    expect(fetchMock).toHaveBeenCalledWith(
      "/api/media/upload",
      expect.objectContaining({ method: "POST" }),
    )
  })

  it("shows network error message when request throws", async () => {
    vi.spyOn(globalThis, "fetch").mockRejectedValue(new Error("network down"))

    render(<MediaUploadForm />)

    const form = screen.getByRole("button", { name: "Upload media" }).closest("form")

    if (!form) {
      throw new Error("Upload form not found")
    }

    const fileInput = screen.getByLabelText("File") as HTMLInputElement
    fireEvent.change(fileInput, {
      target: {
        files: [new File(["x"], "demo.png", { type: "image/png" })],
      },
    })

    fireEvent.submit(form)

    await waitFor(() => {
      expect(screen.queryByText("Upload request failed. Please retry.")).not.toBeNull()
    })
  })
})
