import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { QuestionField } from "@/lib/schema-adapter";
import { mapBackendQuestionToFrontend } from "@/lib/schema-adapter";
import { QuestionSlider } from "./question-slider";

let answerValue: any = null;
const setAnswerValueMock = vi.fn();

vi.mock("@/translations/provider", () => ({
  useI18n: () => ({
    locale: "en",
    dictionary: { From: "From", To: "To" },
  }),
}));

vi.mock("./question-answer-storage", () => ({
  useQuestionAnswers: () => ({
    getAnswerValue: () => answerValue,
    setAnswerValue: setAnswerValueMock,
  }),
}));

describe("QuestionSlider", () => {
  beforeEach(() => {
    answerValue = null;
    setAnswerValueMock.mockClear();
  });

  afterEach(() => {
    cleanup();
  });

  it("extracts range correctly from backend validation schema", () => {
    const backendQuestion = {
      id: "appearance_health_activity.height_in_centimeters",
      title: "Height in Centimeters",
      type: "scale",
      order: 1,
      required: true,
      is_required: true,
      show_guardian_notice: false,
      validation: { min: 100, max: 230 },
      ui_config: { placeholder_en: "175", private: true },
      logic: null,
      is_visible: true,
      options: [],
      description: "",
      tooltip: "",
      placeholder: "175",
    };

    const frontendQ = mapBackendQuestionToFrontend(backendQuestion as any, 0);
    expect(frontendQ.extras.range).toEqual([100, 230]);
  });

  it("renders scale marks correctly across the range", () => {
    const heightQuestion = {
      id: "appearance_health_activity.height_in_centimeters",
      title: "Height in Centimeters",
      type: "scale",
      order: 1,
      required: true,
      baseRequired: true,
      isVisible: true,
      description: "",
      tooltip: "",
      extras: { placeHolder: "175", range: [100, 230], options: [] },
      options: [],
      validation: { min: 100, max: 230 },
    } as QuestionField;

    answerValue = 178;
    render(<QuestionSlider question={heightQuestion} />);

    const slider = screen.getByRole("slider") as HTMLInputElement;
    expect(slider.min).toBe("100");
    expect(slider.max).toBe("230");
    expect(slider.value).toBe("178");

    // The value badge shows 178
    expect(screen.getByText("178")).toBeDefined();

    // Scale marks should be rendered with multiple ticks (100, 120, ..., 230)
    expect(screen.getByText("100")).toBeDefined();
    expect(screen.getByText("230")).toBeDefined();
    expect(screen.queryByText("0")).toBeNull();
  });

  it("updates answer value when slider changes", () => {
    const weightQuestion = {
      id: "appearance_health_activity.weight_in_kilograms",
      title: "Weight in Kilograms",
      type: "scale",
      order: 2,
      required: true,
      baseRequired: true,
      isVisible: true,
      description: "",
      tooltip: "",
      extras: { placeHolder: "70", range: [40, 180], options: [] },
      options: [],
      validation: { min: 40, max: 180 },
    } as QuestionField;

    render(<QuestionSlider question={weightQuestion} />);

    const slider = screen.getByRole("slider");
    fireEvent.change(slider, { target: { value: "85" } });

    expect(setAnswerValueMock).toHaveBeenCalledWith(weightQuestion, 85);
  });

  it("falls back gracefully when range is not in extras but in validation", () => {
    const customQuestion = {
      id: "custom_scale",
      title: "Satisfaction",
      type: "scale",
      order: 3,
      required: true,
      baseRequired: true,
      isVisible: true,
      description: "",
      tooltip: "",
      extras: { placeHolder: "5", range: [0, 0], options: [] },
      options: [],
      validation: { min: 1, max: 10 },
    } as QuestionField;

    render(<QuestionSlider question={customQuestion} />);

    const slider = screen.getByRole("slider") as HTMLInputElement;
    expect(slider.min).toBe("1");
    expect(slider.max).toBe("10");
    expect(screen.getByText("1")).toBeDefined();
    expect(screen.getByText("10")).toBeDefined();
  });
});
