import { render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { vi, describe, it, expect, beforeEach } from "vitest";
import type { CheckinBrandingData } from "@alqove/api-client";
import { CheckinForm } from "../CheckinForm";

const BRANDING: CheckinBrandingData = {
  name: "Wax & Wane Records",
  logo: null,
  description: null,
  hours: null,
  status_visibility: "live",
  terms_version: "2026-01",
  checkin_enabled: true,
  checkin_paused: false,
};

function renderForm(onSubmit = vi.fn()) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(
    <QueryClientProvider client={qc}>
      <CheckinForm token="tok1" branding={BRANDING} onSubmit={onSubmit} />
    </QueryClientProvider>,
  );
  return onSubmit;
}

async function fillPhoneStep(user: ReturnType<typeof userEvent.setup>) {
  await user.type(screen.getByLabelText(/first name/i), "Ada");
  await user.type(screen.getByLabelText(/last name/i), "Lovelace");
  await user.type(screen.getByLabelText(/phone/i), "5125551234");
}

describe("CheckinForm wizard", () => {
  beforeEach(() => {
    localStorage.clear();
  });

  it("phone input is tel-optimized and labeled", () => {
    renderForm();
    const phone = screen.getByLabelText(/phone/i);
    expect(phone).toHaveAttribute("inputmode", "tel");
    expect(phone).toHaveAttribute("type", "tel");
  });

  it("blocks advancing from the phone step until name + valid phone are present", async () => {
    const user = userEvent.setup();
    renderForm();

    const next = screen.getByRole("button", { name: /next/i });
    expect(next).toBeDisabled();

    await user.type(screen.getByLabelText(/first name/i), "Ada");
    await user.type(screen.getByLabelText(/last name/i), "Lovelace");
    await user.type(screen.getByLabelText(/phone/i), "12345"); // too short
    expect(next).toBeDisabled();

    await user.clear(screen.getByLabelText(/phone/i));
    await user.type(screen.getByLabelText(/phone/i), "5125551234");
    expect(next).toBeEnabled();
  });

  it("walks through all three steps and submits the assembled payload", async () => {
    const user = userEvent.setup();
    const onSubmit = renderForm();

    // Step 1 — phone
    await fillPhoneStep(user);
    await user.click(screen.getByRole("button", { name: /next/i }));

    // Step 2 — containers
    const count = screen.getByLabelText(/number of containers/i);
    expect(count).toHaveValue(1);
    await user.click(screen.getByRole("button", { name: /increase/i }));
    await user.click(screen.getByRole("button", { name: /increase/i }));
    expect(count).toHaveValue(3);
    await user.type(
      screen.getByLabelText(/describe/i),
      "two totes + a box",
    );
    await user.click(screen.getByRole("button", { name: /next/i }));

    // Step 3 — review + opt-ins
    await user.click(screen.getByLabelText(/loyalty/i));
    await user.click(screen.getByLabelText(/text me|sms|updates/i));
    await user.click(screen.getByRole("button", { name: /check in|submit/i }));

    expect(onSubmit).toHaveBeenCalledTimes(1);
    expect(onSubmit).toHaveBeenCalledWith({
      first_name: "Ada",
      last_name: "Lovelace",
      phone: "5125551234",
      container_count: 3,
      container_description: "two totes + a box",
      opt_loyalty: true,
      opt_txn: true,
      opt_promo: false,
    });
  });

  it("clamps the container stepper to the 1–20 range", async () => {
    const user = userEvent.setup();
    renderForm();
    await fillPhoneStep(user);
    await user.click(screen.getByRole("button", { name: /next/i }));

    const decrease = screen.getByRole("button", { name: /decrease/i });
    const count = screen.getByLabelText(/number of containers/i);
    expect(count).toHaveValue(1);
    await user.click(decrease); // cannot go below 1
    expect(count).toHaveValue(1);
    expect(decrease).toBeDisabled();
  });

  it("lets the customer go back to a previous step without losing data", async () => {
    const user = userEvent.setup();
    renderForm();
    await fillPhoneStep(user);
    await user.click(screen.getByRole("button", { name: /next/i }));
    await user.click(screen.getByRole("button", { name: /back/i }));

    expect(screen.getByLabelText(/first name/i)).toHaveValue("Ada");
    expect(screen.getByLabelText(/phone/i)).toHaveValue("5125551234");
  });

  it("shows an optional log-in affordance on the review step", async () => {
    const user = userEvent.setup();
    renderForm();
    await fillPhoneStep(user);
    await user.click(screen.getByRole("button", { name: /next/i }));
    await user.click(screen.getByRole("button", { name: /next/i }));

    const review = screen.getByRole("group", { name: /review/i });
    expect(within(review).getByRole("link", { name: /log in/i })).toBeInTheDocument();
  });
});
