/**
 * Backoffice config validation suite (matrix Suite H). The global ValidationPipe in src/main.ts:56
 * enforces exactly these class-validator DTOs, so validating the DTOs directly reproduces what a
 * raw API call (bypassing the HTML-only frontend checks) would be allowed to submit.
 *   H1 🔴 CreateFareRuleDto.baseFareMinor accepts NEGATIVE (no @Min) — while the sibling
 *          CreateSegmentFareDto.baseFareMinor has @Min(0) (inconsistent). Still unfixed.
 *   H2 ✅ FIXED (was 🔴 "CreateSeatClassDto.basePrice accepts negative/zero, no @Min"):
 *          seat-classes.dto.ts now has @Min(0) on basePrice. Test updated to assert the fix.
 *   H4 ✅ FIXED (was 🔴 "CreatePromotionDto.percentOff accepts 200, no @Max(100)"):
 *          promos.dto.ts now has @Min(0) @Max(100) on percentOff. Test updated to assert the fix.
 *   H5 🔴 CreatePromotionDto.validUntil is @IsString (not @IsDateString) → accepts non-dates.
 *          Still unfixed.
 */
import "reflect-metadata";
import { plainToInstance } from "class-transformer";
import { validate } from "class-validator";

import { CreateFareRuleDto } from "../src/modules/schedules/schedules.dto";
import { CreateSegmentFareDto } from "../src/modules/segments/segment-fare.dto";
import { CreateSeatClassDto } from "../src/modules/seat-classes/seat-classes.dto";
import { CreatePromotionDto } from "../src/modules/promos/promos.dto";

/** Property names that produced a validation error. */
async function erroredProps(dto: object): Promise<string[]> {
  const errors = await validate(dto);
  return errors.map((e) => e.property);
}

describe("Backoffice config validation (Suite H)", () => {
  it("H1 🔴 CreateFareRuleDto accepts a NEGATIVE baseFareMinor (no @Min)", async () => {
    const dto = plainToInstance(CreateFareRuleDto, {
      seatClassId: "sc-1",
      baseFareMinor: -100,
      validFrom: "2026-01-01T00:00:00Z",
    });
    expect(await erroredProps(dto)).not.toContain("baseFareMinor");
  });

  it("H1 contrast: sibling CreateSegmentFareDto REJECTS negative baseFareMinor (@Min(0))", async () => {
    const dto = plainToInstance(CreateSegmentFareDto, {
      routeId: "rt-1",
      originStopSequence: 1,
      destinationStopSequence: 5,
      seatClassId: "sc-1",
      baseFareMinor: -100,
    });
    expect(await erroredProps(dto)).toContain("baseFareMinor");
  });

  it("H2 ✅ CreateSeatClassDto rejects a negative basePrice (@Min(0))", async () => {
    const dto = plainToInstance(CreateSeatClassDto, {
      coachTypeId: "ct-1",
      name: "Economy",
      basePrice: -5000,
    });
    expect(await erroredProps(dto)).toContain("basePrice");
  });

  it("H4 ✅ CreatePromotionDto rejects percentOff = 200 (@Max(100))", async () => {
    const dto = plainToInstance(CreatePromotionDto, {
      code: "OVER",
      title: "Overshoot",
      percentOff: 200,
      validUntil: "2026-12-31T23:59:59Z",
    });
    expect(await erroredProps(dto)).toContain("percentOff");
  });

  it("H5 🔴 CreatePromotionDto.validUntil accepts a non-date string (@IsString, not @IsDateString)", async () => {
    const dto = plainToInstance(CreatePromotionDto, {
      code: "BADDATE",
      title: "Bad date",
      validUntil: "not-a-real-date",
    });
    expect(await erroredProps(dto)).not.toContain("validUntil");
  });
});
