import { type DataTable, Given, Then, When } from "@badeball/cypress-cucumber-preprocessor";

/**
 * One data-table row → a fake `ShoppingListItemView` — same minimal-fixture
 * convention as `recipe-form.ts`'s ingredient fixtures (only the fields
 * `ShoppingListPage` actually reads at runtime: the ingredient's `key`/
 * `icon`/`category` for `IngredientTypeIcon`/`CategoryIcon`/translation, the
 * unit's `key`; `id` only needs to be unique per row for the React list
 * key). `index` seeds both ids so two rows never collide.
 */
function buildShoppingListItem(
  row: { ingredientKey: string; icon: string; category: string; quantity: string; unitKey: string },
  index: number,
) {
  return {
    ingredient: {
      id: index,
      key: row.ingredientKey,
      icon: row.icon,
      category: row.category,
      subcategory: row.category,
      reproducible: false,
      allergens: [],
      diets: [],
    },
    quantity: Number(row.quantity),
    unit: { id: index, key: row.unitKey, type: "MASS", toBaseFactor: 1 },
  };
}

Given("the shopping list for {string} is empty", (date: string) => {
  cy.intercept("GET", `**/shopping-list?date=${date}`, {
    statusCode: 200,
    body: { startDate: date, finishDate: date, items: [] },
  });
});

Given("the shopping list for {string} contains:", (date: string, dataTable: DataTable) => {
  const items = dataTable.hashes().map((row, i) => buildShoppingListItem(row, i + 1));
  cy.intercept("GET", `**/shopping-list?date=${date}`, {
    statusCode: 200,
    body: { startDate: date, finishDate: date, items },
  });
});

// Same class as PlanningPage's own week navigator (`WeekNavigator`, now
// shared between the two pages) — `planning-page.cy.ts` already exercises
// the prev/next arrows directly by class, same approach here.
When("I click the next week arrow", () => {
  cy.get(".week-nav__arrow").last().click();
});

Then(
  "the shopping list group {string} should appear before {string}",
  (first: string, second: string) => {
    cy.get(".shopping-list__group-title").then(($titles) => {
      const texts = [...$titles].map((el) => el.textContent?.trim() ?? "");
      const firstIndex = texts.findIndex((text) => text.includes(first));
      const secondIndex = texts.findIndex((text) => text.includes(second));
      expect(firstIndex, `"${first}" should be a rendered group`).to.be.greaterThan(-1);
      expect(secondIndex, `"${second}" should be a rendered group`).to.be.greaterThan(-1);
      expect(firstIndex).to.be.lessThan(secondIndex);
    });
  },
);

Then(
  "the shopping list should show {string} at quantity {string}",
  (name: string, quantity: string) => {
    cy.contains(".shopping-list__item", name).should("contain.text", quantity);
  },
);
