/**
 * @vitest-environment jsdom
 */
import {
  cleanup,
  fireEvent,
  render,
  screen,
  waitFor,
} from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import PriceForm from "./price-form";

globalThis.ResizeObserver = class ResizeObserver {
  observe() {
    return;
  }
  unobserve() {
    return;
  }
  disconnect() {
    return;
  }
};
Element.prototype.scrollIntoView = function scrollIntoView() {
  return;
};

vi.mock("react-i18next", () => ({
  useTranslation: () => ({
    t: (_key: string, fallback: string): string => fallback,
  }),
}));

const rules: API.PromoRule[] = [
  {
    id: 1,
    name: "Campaign Rule",
    type: "campaign",
    params: {},
    priority: 1,
    enabled: true,
  },
];

const subscribes: API.SubscribeItem[] = [
  {
    id: 8,
    name: "Monthly Plan",
    unit_price: 1200,
    unit_time: "Month",
    sold: 0,
    discount: [
      {
        quantity: 3,
        discount: 90,
      },
    ],
  },
];
const subscribesWithoutDiscounts: API.SubscribeItem[] = [
  {
    id: 8,
    name: "Monthly Plan",
    unit_price: 1200,
    unit_time: "Month",
    sold: 0,
    discount: [],
  },
];

async function selectCombobox(index: number, option: string) {
  const combobox = screen.getAllByRole("combobox")[index];
  if (!combobox) throw new Error(`Combobox ${index} not found`);
  fireEvent.click(combobox);
  fireEvent.click(await screen.findByText(option));
}

afterEach(() => {
  cleanup();
  vi.clearAllMocks();
});

describe("PriceForm", () => {
  it("submits promo price with promo_rule_id and selected quantity item", async () => {
    const onSubmit = vi.fn().mockResolvedValue(true);
    render(
      <PriceForm onSubmit={onSubmit} rules={rules} subscribes={subscribes} />
    );

    fireEvent.click(screen.getByRole("button", { name: "Create Promo Price" }));
    await selectCombobox(0, "Campaign Rule");
    await selectCombobox(1, "Monthly Plan");
    await selectCombobox(2, "3 x Month");
    fireEvent.change(screen.getByPlaceholderText("Enter price"), {
      target: { value: "20" },
    });
    fireEvent.click(screen.getByRole("button", { name: "Confirm" }));

    await waitFor(() =>
      expect(onSubmit).toHaveBeenCalledWith({
        promo_rule_id: 1,
        items: [{ subscribe_id: 8, quantity: 3, promo_price: 2000 }],
      })
    );
  });

  it("blocks submit when subscribe has no discount quantities", async () => {
    const onSubmit = vi.fn();
    render(
      <PriceForm
        onSubmit={onSubmit}
        rules={rules}
        subscribes={subscribesWithoutDiscounts}
      />
    );

    fireEvent.click(screen.getByRole("button", { name: "Create Promo Price" }));
    await selectCombobox(1, "Monthly Plan");

    expect(
      screen.getByText(
        "This subscribe has no discount quantities and cannot be configured."
      )
    ).not.toBeNull();
    expect(screen.getByRole("button", { name: "Confirm" })).toHaveProperty(
      "disabled",
      true
    );
  });

  it("keeps the form open and shows an error when promo price reaches original price", async () => {
    const onSubmit = vi.fn();
    render(
      <PriceForm onSubmit={onSubmit} rules={rules} subscribes={subscribes} />
    );

    fireEvent.click(screen.getByRole("button", { name: "Create Promo Price" }));
    await selectCombobox(0, "Campaign Rule");
    await selectCombobox(1, "Monthly Plan");
    await selectCombobox(2, "3 x Month");
    fireEvent.change(screen.getByPlaceholderText("Enter price"), {
      target: { value: "36" },
    });
    fireEvent.click(screen.getByRole("button", { name: "Confirm" }));

    expect(
      await screen.findByText("Promo price must be lower than original price")
    ).not.toBeNull();
    expect(onSubmit).not.toHaveBeenCalled();
  });
});
