/**
 * BOOKING — clearance document QUERY (reject) + re-upload lifecycle:
 *
 *   Every other spec that touches clearance only ever APPROVES documents
 *   (`clearGeneralBooking` in import-utils.ts). This spec drives the other
 *   branch of `reviewDocument` — QUERIED — which no spec exercises:
 *
 *     – querying a document with no note is rejected (a note is required)
 *     – querying with a note succeeds: reviewStatus → QUERIED, the note is
 *       stored, and a CHANGES_REQUESTED review note is recorded on the booking
 *     – re-uploading the SAME document resets its review to PENDING (the
 *       customer's fix clears the query — submitClearanceDocuments always
 *       resets reviewed docs back to PENDING on re-upload)
 *     – GL re-reviews it APPROVED → finalize succeeds → CLEARANCE_READY
 *
 * GENERAL contract, per-booking clearance gate (AWAITING_DOCUMENTS at
 * creation, before ops ever sees it) — same fixture shape as
 * clearGeneralBooking, with an ad-hoc document. Retries off.
 */

import {
  apiPost,
  bookContainers,
  db,
  departureAt,
  eatDayStr,
  glUpload,
  seedImportContract,
  superAdmin,
  withBooking,
} from "./import-utils";

const stamp = String(Date.now());
// Per-booking clearance (Path A) skips the booking-window gate entirely, so
// this date never needs a real schedule behind it — just a binding day string.
const BOOKING_DAY = eatDayStr(departureAt(33));

interface ReviewRow {
  status: string;
  note: string | null;
}

function reviewFor(bookingId: string, fn: (row: ReviewRow) => void) {
  db<ReviewRow>(
    `SELECT status, note FROM freight.booking_document_review
      WHERE booking_id = $1 AND file_key = 'custom_e2e'`,
    [bookingId],
  ).then(({ rows }) => {
    expect(rows, "review row for custom_e2e").to.have.length(1);
    fn(rows[0]);
  });
}

describe("booking: clearance document query (reject) + re-upload lifecycle", { retries: 0 }, () => {
  before(() => {
    cy.task("db:seedFile", "seed-import-corridor.sql");
    seedImportContract({ suffix: "CQ1", reference: `CTR-IMP-${stamp}-CQ1`, kind: "GENERAL" });
  });

  it("books under the GENERAL contract — starts at the clearance gate", () => {
    bookContainers({
      suffix: "CQ1",
      runStamp: stamp,
      isoSeed: 0,
      forty: 1,
      scheduledDate: BOOKING_DAY,
    });
    withBooking("CQ1", (b) =>
      expect(b.status, "AWAITING_DOCUMENTS").to.eq("AWAITING_DOCUMENTS"),
    );
  });

  it("uploads a document; querying it with no note is rejected", () => {
    withBooking("CQ1", (b) => {
      glUpload(`/api/bookings/${b.id}/clearance/documents`, {}, "custom_e2e");

      apiPost(
        superAdmin,
        `/api/bookings/${b.id}/clearance/review`,
        { fileKey: "custom_e2e", status: "QUERIED" },
        false,
      ).then((res) => {
        expect(res.status, "note required").to.be.within(400, 422);
        expect(JSON.stringify(res.body)).to.include("A note is required");
      });
    });
  });

  it("querying with a note succeeds — reviewStatus QUERIED, note stored, review note recorded", () => {
    withBooking("CQ1", (b) => {
      apiPost(superAdmin, `/api/bookings/${b.id}/clearance/review`, {
        fileKey: "custom_e2e",
        status: "QUERIED",
        note: "E2E: wrong document, please re-upload the correct one",
      }).then((res) => expect(res.status, "queried").to.be.oneOf([200, 201]));

      reviewFor(b.id, (row) => {
        expect(row.status, "QUERIED").to.eq("QUERIED");
        expect(row.note, "note stored").to.include("wrong document");
      });

      db<{ n: string }>(
        `SELECT count(*) AS n FROM freight.booking_review_note
          WHERE booking_id = $1 AND type = 'CHANGES_REQUESTED'`,
        [b.id],
      ).then(({ rows }) =>
        expect(Number(rows[0].n), "queried review note recorded").to.be.at.least(1),
      );

      // Still under review — the query doesn't advance the booking status.
      withBooking("CQ1", (fresh) =>
        expect(fresh.status, "still DOCUMENTS_UNDER_REVIEW").to.eq("DOCUMENTS_UNDER_REVIEW"),
      );
    });
  });

  it("re-uploading resets the review to PENDING; GL approves it and finalize succeeds", () => {
    withBooking("CQ1", (b) => {
      glUpload(`/api/bookings/${b.id}/clearance/documents`, {}, "custom_e2e");

      reviewFor(b.id, (row) => expect(row.status, "reset to PENDING").to.eq("PENDING"));

      apiPost(superAdmin, `/api/bookings/${b.id}/clearance/review`, {
        fileKey: "custom_e2e",
        status: "APPROVED",
      }).then((res) => expect(res.status, "approved").to.be.oneOf([200, 201]));

      reviewFor(b.id, (row) => expect(row.status, "APPROVED").to.eq("APPROVED"));

      apiPost(superAdmin, `/api/bookings/${b.id}/clearance/finalize`).then((res) =>
        expect(res.status, "finalized").to.be.oneOf([200, 201]),
      );
    });

    withBooking("CQ1", (b) =>
      expect(b.status, "CLEARANCE_READY").to.eq("CLEARANCE_READY"),
    );
  });
});

export {};
