import "../../src/i18n/i18n";
import { TechStepCorrectionPopover } from "../../src/features/recipes/steps/TechStepCorrectionPopover";

// Mounts the popover in isolation (no StepDescription/selection plumbing
// around it) — same "generic component test" posture as CheckboxOption.cy.tsx,
// but this one needs `../../src/i18n/i18n` imported for its side effect
// (initializes the default i18next instance `useTranslation` falls back to
// with no `<I18nextProvider>` in the tree — see that module's own doc
// comment) since, unlike Checkbox/Radio, this component calls
// `useTranslation()`.

const cook = { id: 1, key: "cook" };
const simmer = { id: 3, key: "simmer" };

function mountPopover(
  overrides: Partial<{
    previousTechStepId: number | null;
    onClose: () => void;
    onSubmitted: (correction: unknown) => void;
  }> = {},
) {
  cy.mount(
    <div>
      {/* A genuinely separate sibling to click for the "outside click closes it" test — clicking blindly at a viewport coordinate would risk still landing inside the popover, which fills most of the mounted area on its own. */}
      <div data-testid="outside-popover" style={{ height: 20 }} />
      <TechStepCorrectionPopover
        recipeId={2}
        stepId={2}
        selectedText="Cuire"
        range={{ start: 0, end: 5 }}
        previousTechStepId={overrides.previousTechStepId ?? null}
        onClose={overrides.onClose ?? (() => {})}
        onSubmitted={overrides.onSubmitted ?? (() => {})}
      />
    </div>,
  );
}

describe("TechStepCorrectionPopover", () => {
  beforeEach(() => {
    cy.intercept("GET", "**/reference/tech-steps", { statusCode: 200, body: [cook, simmer] }).as(
      "getTechSteps",
    );
  });

  it("shows the selected text and every technique option once loaded", () => {
    mountPopover();
    cy.wait("@getTechSteps");

    cy.contains(".tech-step-correction-popover__selection", "Cuire").should("be.visible");
    cy.get(".tech-step-correction-popover__list button").should("have.length", 2);
  });

  it("offers a 'no technique here' option only when correcting an existing match", () => {
    mountPopover({ previousTechStepId: null });
    cy.wait("@getTechSteps");
    cy.get(".tech-step-correction-popover__remove").should("not.exist");

    mountPopover({ previousTechStepId: cook.id });
    cy.wait("@getTechSteps");
    cy.get(".tech-step-correction-popover__remove").should("exist");
  });

  it("submits the selected technique and calls onSubmitted", () => {
    // Asserting on the resolved `@submitCorrection` interception below,
    // rather than inside this handler — a Chai assertion failing *inside*
    // a `cy.intercept` callback surfaces as an opaque "onResponse cannot be
    // called twice" Cypress internal error instead of a normal assertion
    // failure, found while writing this exact test.
    cy.intercept("POST", "**/recipes/2/steps/2/corrections", {
      statusCode: 201,
      body: {
        id: 1,
        start: 0,
        end: 5,
        previousTechStep: null,
        correctedTechStep: simmer,
        createdAt: new Date().toISOString(),
      },
    }).as("submitCorrection");
    const onSubmitted = cy.stub().as("onSubmitted");
    mountPopover({ onSubmitted });
    cy.wait("@getTechSteps");

    cy.contains(".tech-step-correction-popover__list button", "Mijoter").click();

    cy.wait("@submitCorrection").its("request.body").should("deep.equal", {
      start: 0,
      end: 5,
      previousTechStepId: null,
      correctedTechStepId: simmer.id,
    });
    cy.get("@onSubmitted").should("have.been.calledOnce");
  });

  it("shows an error message and stays open when the submission fails", () => {
    cy.intercept("POST", "**/recipes/2/steps/2/corrections", {
      statusCode: 404,
      body: { code: 4051, message: "TechStep not found" },
    }).as("submitCorrection");
    const onClose = cy.stub().as("onClose");
    mountPopover({ onClose });
    cy.wait("@getTechSteps");

    cy.contains(".tech-step-correction-popover__list button", "Cuire").click();

    cy.wait("@submitCorrection");
    cy.get(".field-error").should("be.visible");
    cy.get("@onClose").should("not.have.been.called");
  });

  it("calls onClose on an outside click", () => {
    const onClose = cy.stub().as("onClose");
    mountPopover({ onClose });
    cy.wait("@getTechSteps");

    cy.get('[data-testid="outside-popover"]').click();

    cy.get("@onClose").should("have.been.calledOnce");
  });
});
