/// <reference types="cypress" />

type NotificationRecord = {
  id: string;
  title: string;
  event_type: string;
  created_at: number;
  message: string;
  priority: string;
  type: string;
  seen: boolean;
  status: string;
  recipient?: { full_name: string };
};

const notificationHistoryPattern = /\/api\/proxy\/notifications(?:\?|$)/;

const makeNotification = (
  overrides: Partial<NotificationRecord> = {},
): NotificationRecord => ({
  id: "notification-1",
  title: "Tender deadline reminder",
  event_type: "push",
  created_at: 1_717_934_400,
  message: "A watched tender is closing soon and needs your attention.",
  priority: "important",
  type: "warning",
  seen: false,
  status: "sent",
  recipient: { full_name: "E2E Admin One" },
  ...overrides,
});

const historyResponse = (
  notifications: NotificationRecord[],
  options: { offset?: number; total?: number; pages?: number } = {},
) => ({
  success: true,
  message: "ok",
  data: notifications,
  meta: {
    offset: options.offset ?? 0,
    limit: 10,
    total: options.total ?? notifications.length,
    page: Math.floor((options.offset ?? 0) / 10) + 1,
    pages: options.pages ?? 1,
    has_more: false,
  },
});

const stubHeaderNotifications = (times = 1) => {
  cy.intercept(
    {
      method: "GET",
      url: "**/api/proxy/notifications/my**",
      times,
    },
    {
      statusCode: 200,
      body: historyResponse([]),
    },
  ).as("myNotifications");
};

describe("notification history", () => {
  beforeEach(() => {
    cy.setAuthCookies();
    stubHeaderNotifications();
  });

  it("renders breadcrumbs, actions, columns, API rows, and details navigation", () => {
    const notification = makeNotification();

    cy.intercept("GET", notificationHistoryPattern, (req) => {
      expect(req.query).to.include({
        sort_by: "created_at",
        sort_order: "desc",
        offset: "0",
        limit: "10",
      });
      req.reply({
        statusCode: 200,
        body: historyResponse([notification]),
      });
    }).as("notificationHistory");

    cy.visit("/notification-history");
    cy.wait("@notificationHistory");

    cy.getByCy("breadcrumb-link-dashboard").should("be.visible");
    cy.getByCy("breadcrumb-current-notification-history")
      .should("be.visible")
      .and("contain.text", "Notification history");
    cy.getByCy("list-header-create-button").should(
      "contain.text",
      "Create notification",
    );

    [
      "row",
      "title",
      "channel",
      "created at",
      "receiver",
      "message",
      "priority",
      "type",
      "seen",
      "status",
      "actions",
    ].forEach((column) => {
      cy.contains("th", new RegExp(`^${column}$`, "i")).should("exist");
    });

    cy.contains("tr", notification.title)
      .should("contain.text", notification.event_type)
      .and("contain.text", notification.recipient?.full_name)
      .and("contain.text", notification.priority)
      .and("contain.text", notification.type)
      .and("contain.text", notification.status)
      .within(() => {
        cy.get('button[data-tooltip-id="details"]').click();
      });

    cy.location("pathname").should(
      "eq",
      `/notification-history/${notification.id}`,
    );
  });

  it("filters by seen state and search, then resets to the default list", () => {
    const defaultNotification = makeNotification({
      id: "notification-default",
      title: "Default notification",
    });
    const filteredNotification = makeNotification({
      id: "notification-filtered",
      title: "Filtered urgent notice",
      seen: true,
    });

    cy.intercept("GET", notificationHistoryPattern, (req) => {
      const isFiltered =
        req.query.seen === "true" && req.query.search === "urgent";
      req.alias = isFiltered ? "filteredNotifications" : "defaultNotifications";
      req.reply({
        statusCode: 200,
        body: historyResponse([
          isFiltered ? filteredNotification : defaultNotification,
        ]),
      });
    });

    cy.visit("/notification-history");
    cy.wait("@defaultNotifications");
    cy.contains(defaultNotification.title).should("be.visible");

    cy.getByCy("notification-history-filter-panel-toggle").click();
    cy.get('select[name="seen"]').select("true", { force: true });
    cy.getByCy("notification-history-filter-search-input").type("urgent");
    cy.getByCy("notification-history-filter-submit-button").click();

    cy.wait("@filteredNotifications");
    cy.location("search")
      .should("include", "seen=true")
      .and("include", "search=urgent");
    cy.contains(filteredNotification.title).should("be.visible");
    cy.contains(defaultNotification.title).should("not.exist");
    cy.contains("2 active").should("be.visible");

    cy.getByCy("notification-history-filter-reset-button").click();
    cy.wait("@defaultNotifications");
    cy.location("search").should("eq", "");
    cy.contains(defaultNotification.title).should("be.visible");
  });

  it("filters notification history by user when a user is selected", () => {
    const currentUserNotification = makeNotification({
      id: "notification-current-user",
      title: "Current user notification",
    });
    const selectedUserNotification = makeNotification({
      id: "notification-selected-user",
      title: "Selected user notification",
      recipient: { full_name: "Notification Admin" },
    });

    cy.intercept("GET", notificationHistoryPattern, {
      statusCode: 200,
      body: historyResponse([currentUserNotification]),
    }).as("currentUserNotifications");

    cy.intercept("GET", "**/api/proxy/users**", {
      statusCode: 200,
      body: {
        success: true,
        message: "ok",
        data: {
          users: [
            {
              id: "64f9b24d2f1b2f0012345678",
              full_name: "Notification Admin",
              username: "notification-admin",
              email: "notification-admin@example.com",
              role: "admin",
              status: "active",
            },
          ],
        },
        meta: {
          offset: 0,
          limit: 20,
          total: 1,
          page: 1,
          pages: 1,
          has_more: false,
        },
      },
    }).as("users");

    cy.intercept("GET", notificationHistoryPattern, (req) => {
      expect(req.query.user_id).to.eq("64f9b24d2f1b2f0012345678");
      req.reply({
        statusCode: 200,
        body: historyResponse([selectedUserNotification]),
      });
    }).as("selectedUserNotifications");

    cy.visit("/notification-history");
    cy.wait("@currentUserNotifications");
    cy.contains(currentUserNotification.title).should("be.visible");

    cy.getByCy("notification-history-filter-panel-toggle").click();
    cy.getByCy("notification-history-filter-user-select")
      .siblings("button")
      .click();
    cy.getByCy("notification-history-filter-user-select-search").type(
      "Notification Admin",
    );
    cy.wait("@users");
    cy.getByCy("notification-history-filter-user-select-option")
      .filter('[data-value="64f9b24d2f1b2f0012345678"]')
      .click();
    cy.getByCy("notification-history-filter-submit-button").click();

    cy.wait("@selectedUserNotifications");
    cy.location("search").should(
      "include",
      "user_id=64f9b24d2f1b2f0012345678",
    );
    cy.contains(selectedUserNotification.title).should("be.visible");
    cy.contains(currentUserNotification.title).should("not.exist");
  });

  it("shows the current user filter when notification history is opened for the current user", () => {
    const notification = makeNotification({
      id: "notification-current-user-filter",
      title: "Current user filtered notification",
    });

    cy.intercept("GET", notificationHistoryPattern, (req) => {
      expect(req.query.user_id).to.eq("507f1f77bcf86cd799439011");
      req.reply({
        statusCode: 200,
        body: historyResponse([notification]),
      });
    }).as("currentUserFilteredNotifications");

    cy.visit("/notification-history?user_id=507f1f77bcf86cd799439011");
    cy.wait("@currentUserFilteredNotifications");

    cy.getByCy("notification-history-filter-panel-toggle").should(
      "contain.text",
      "1 active",
    );
    cy.getByCy("notification-history-filter-panel-toggle").click();
    cy.getByCy("notification-history-filter-user-select")
      .siblings("button")
      .should("contain.text", "E2E Admin One");
    cy.contains(notification.title).should("be.visible");
  });

  it("shows loading and empty states, and opens the create page", () => {
    cy.intercept("GET", notificationHistoryPattern, (req) => {
      req.reply({
        delay: 900,
        statusCode: 200,
        body: historyResponse([]),
      });
    }).as("emptyNotificationHistory");

    cy.visit("/notification-history");
    cy.getByCy("table-skeleton").should("be.visible");
    cy.wait("@emptyNotificationHistory");
    cy.getByCy("table-skeleton").should("not.exist");
    cy.getByCy("empty-list-message").should(
      "contain.text",
      "No notifications were found",
    );

    cy.getByCy("list-header-create-button").click();
    cy.location("pathname").should("eq", "/notification-history/create");
    cy.getByCy("breadcrumb-current-create-notification").should("be.visible");
  });
});
