// @vitest-environment jsdom

import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { ClassesRequestForm } from "@/components/classes-request-form";

const fetchMock = vi.fn();

describe("ClassesRequestForm", () => {
  beforeEach(() => {
    vi.stubGlobal("fetch", fetchMock);
  });

  afterEach(() => {
    cleanup();
    fetchMock.mockReset();
    vi.unstubAllGlobals();
  });

  it("submits the selected visible slot as part of the request", async () => {
    fetchMock.mockResolvedValue({
      ok: true,
      json: async () => ({ ok: true, item: { id: "request_001" } }),
    });

    render(
      <ClassesRequestForm
        classOfferId="offer_001"
        slots={[
          {
            start: "2026-03-31T01:00:00.000Z",
            durationMinutes: 90,
            priceMinor: 22000,
            currency: "ARS",
            sportclubId: "106",
            courtId: "342",
            courtName: "Cancha 1",
          },
        ]}
      />
    );

    fireEvent.click(screen.getAllByRole("radio")[0]!);
    fireEvent.change(screen.getByLabelText("Nombre"), { target: { value: "Micaela Torres" } });
    fireEvent.change(screen.getByLabelText("Email"), { target: { value: "micaela@example.com" } });
    fireEvent.change(screen.getByLabelText("Telefono"), { target: { value: "11 5555 0101" } });
    fireEvent.change(screen.getByLabelText("Mensaje"), { target: { value: "Prefiero este horario." } });
    fireEvent.click(screen.getByRole("button", { name: /solicitar clase/i }));

    await waitFor(() => {
      expect(fetchMock).toHaveBeenCalledWith(
        "/api/classes/requests",
        expect.objectContaining({
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            classOfferId: "offer_001",
            studentName: "Micaela Torres",
            studentEmail: "micaela@example.com",
            studentPhone: "11 5555 0101",
            message: "Prefiero este horario.",
            selectionMode: "slot",
            selectedSlotStart: "2026-03-31T01:00:00.000Z",
            selectedSlotDurationMinutes: 90,
            selectedSlotPriceMinor: 22000,
            selectedSlotCurrency: "ARS",
            selectedAtcSportclubId: "106",
            selectedAtcCourtId: "342",
          }),
        })
      );
    });
  });

  it("submits the flexible fallback without concrete slot fields", async () => {
    fetchMock.mockResolvedValue({
      ok: true,
      json: async () => ({ ok: true, item: { id: "request_002" } }),
    });

    render(
      <ClassesRequestForm
        classOfferId="offer_001"
        slots={[
          {
            start: "2026-03-31T01:00:00.000Z",
            durationMinutes: 90,
            priceMinor: 22000,
            currency: "ARS",
            sportclubId: "106",
            courtId: "342",
            courtName: "Cancha 1",
          },
        ]}
      />
    );

    fireEvent.click(screen.getByLabelText(/cualquier horario \/ lugar/i));
    fireEvent.change(screen.getByLabelText("Nombre"), { target: { value: "Micaela Torres" } });
    fireEvent.change(screen.getByLabelText("Email"), { target: { value: "micaela@example.com" } });
    fireEvent.change(screen.getByLabelText("Mensaje"), { target: { value: "Me sirven varias sedes por la tarde." } });
    fireEvent.click(screen.getByRole("button", { name: /solicitar clase/i }));

    await waitFor(() => {
      expect(fetchMock).toHaveBeenCalledWith(
        "/api/classes/requests",
        expect.objectContaining({
          body: JSON.stringify({
            classOfferId: "offer_001",
            studentName: "Micaela Torres",
            studentEmail: "micaela@example.com",
            studentPhone: "",
            message: "Me sirven varias sedes por la tarde.",
            selectionMode: "flexible",
          }),
        })
      );
    });
  });

  it("announces validation and success states through alert/status semantics", async () => {
    fetchMock.mockResolvedValue({
      ok: true,
      json: async () => ({ ok: true, item: { id: "request_003" } }),
    });

    render(
      <ClassesRequestForm
        classOfferId="offer_001"
        slots={[
          {
            start: "2026-03-31T01:00:00.000Z",
            durationMinutes: 90,
            priceMinor: 22000,
            currency: "ARS",
            sportclubId: "106",
            courtId: "342",
            courtName: "Cancha 1",
          },
        ]}
      />
    );

    fireEvent.change(screen.getByLabelText("Nombre"), { target: { value: "Micaela Torres" } });
    fireEvent.change(screen.getByLabelText("Email"), { target: { value: "micaela@example.com" } });
    fireEvent.click(screen.getByRole("button", { name: /solicitar clase/i }));

    const alert = await screen.findByRole("alert");
    expect(alert.textContent).toMatch(/elige un horario visible o marca cualquier horario/i);
    expect(screen.getByLabelText("Nombre").getAttribute("aria-describedby")).toBe("classes-request-error");

    fireEvent.click(screen.getAllByRole("radio")[0]!);
    fireEvent.click(screen.getByRole("button", { name: /solicitar clase/i }));

    const status = await screen.findByRole("status");
    expect(status.getAttribute("aria-live")).toBe("polite");
    expect(status.textContent).toMatch(/solicitud enviada con el horario elegido/i);
    expect(screen.getByLabelText("Nombre").getAttribute("aria-describedby")).toBe("classes-request-success");
  });

  it("focuses the name input when a slot is already selected or gets selected", async () => {
    const { rerender } = render(
      <ClassesRequestForm
        classOfferId="offer_001"
        slots={[
          {
            start: "2026-03-31T01:00:00.000Z",
            durationMinutes: 90,
            priceMinor: 22000,
            currency: "ARS",
            sportclubId: "106",
            courtId: "342",
            courtName: "Cancha 1",
          },
        ]}
      />
    );

    fireEvent.click(screen.getAllByRole("radio")[0]!);
    await waitFor(() => {
      expect(document.activeElement).toBe(screen.getByLabelText("Nombre"));
    });

    rerender(
      <ClassesRequestForm
        classOfferId="offer_001"
        slots={[
          {
            start: "2026-03-31T01:00:00.000Z",
            durationMinutes: 90,
            priceMinor: 22000,
            currency: "ARS",
            sportclubId: "106",
            courtId: "342",
            courtName: "Cancha 1",
          },
        ]}
        initialSelectedSlot={{
          start: "2026-03-31T01:00:00.000Z",
          durationMinutes: 90,
          priceMinor: 22000,
          currency: "ARS",
          sportclubId: "106",
          courtId: "342",
          courtName: "Cancha 1",
        }}
      />
    );

    await waitFor(() => {
      expect(document.activeElement).toBe(screen.getByLabelText("Nombre"));
    });
  });
});
