/**
 * Tests for the zod-validation in PATCH /api/profile/me/demographics.
 * Replicates the schema from the endpoint to test the validation
 * boundaries (anti-Cascade-Bug: invalid input must 422, not 500).
 *
 * Updated for Demographics Phase D: employmentStatus/shiftWork/industry/jobTenure
 * replace profession. profession kept as legacy optional field.
 */
import { describe, expect, it } from "vitest";
import { z } from "zod";

const BUNDESLAND_REGEX = /^DE-(BW|BY|BE|BB|HB|HH|HE|MV|NI|NW|RP|SL|SN|ST|SH|TH)$/;
const GENDER_VALUES = ["male", "female", "diverse", "no_answer"] as const;
const MARITAL_VALUES = [
  "single",
  "partnered",
  "married",
  "divorced",
  "widowed",
  "no_answer",
] as const;
const EMPLOYMENT_STATUS_VALUES = [
  "employed",
  "self_employed",
  "in_training",
  "unemployed",
  "retired",
  "homemaking",
  "other",
] as const;
const JOB_TENURE_VALUES = [
  "less_1y",
  "1_3y",
  "3_5y",
  "5_10y",
  "more_10y",
] as const;

const Schema = z.object({
  birthYear: z.number().int().min(1920).max(2010).nullable().optional(),
  gender: z.enum(GENDER_VALUES).nullable().optional(),
  maritalStatus: z.enum(MARITAL_VALUES).nullable().optional(),
  profession: z.string().trim().max(80).nullable().optional(), // legacy
  employmentStatus: z.enum(EMPLOYMENT_STATUS_VALUES).nullable().optional(),
  shiftWork: z.boolean().nullable().optional(),
  industry: z.string().trim().max(64).nullable().optional(),
  jobTenure: z.enum(JOB_TENURE_VALUES).nullable().optional(),
  bundesland: z.string().regex(BUNDESLAND_REGEX).nullable().optional(),
  city: z.string().trim().max(80).nullable().optional(),
});

describe("demographics zod schema — happy", () => {
  it("accepts a complete valid demographic payload (new fields)", () => {
    const r = Schema.safeParse({
      birthYear: 1989,
      gender: "diverse",
      maritalStatus: "partnered",
      employmentStatus: "employed",
      shiftWork: true,
      industry: "Gesundheit",
      jobTenure: "3_5y",
      bundesland: "DE-BY",
      city: "München",
    });
    expect(r.success).toBe(true);
  });

  it("accepts old payload with `profession` (backwards-compat)", () => {
    const r = Schema.safeParse({
      birthYear: 1989,
      gender: "diverse",
      maritalStatus: "partnered",
      profession: "Pflege",
      bundesland: "DE-BY",
      city: "München",
    });
    expect(r.success).toBe(true);
  });

  it("accepts a partial subset (1 field at a time)", () => {
    expect(Schema.safeParse({ birthYear: 1989 }).success).toBe(true);
    expect(Schema.safeParse({ city: "Berlin" }).success).toBe(true);
    expect(Schema.safeParse({ employmentStatus: "in_training" }).success).toBe(true);
    expect(Schema.safeParse({ shiftWork: false }).success).toBe(true);
  });

  it("accepts explicit nulls (= clear field)", () => {
    expect(
      Schema.safeParse({ city: null, birthYear: null, employmentStatus: null, shiftWork: null }).success,
    ).toBe(true);
  });
});

describe("demographics zod schema — invalid input must reject (not 500)", () => {
  it("rejects birthYear out of range (< 1920)", () => {
    const r = Schema.safeParse({ birthYear: 1800 });
    expect(r.success).toBe(false);
  });

  it("rejects birthYear out of range (> 2010 = under-13 protection)", () => {
    const r = Schema.safeParse({ birthYear: 2024 });
    expect(r.success).toBe(false);
  });

  it("rejects unknown gender enum", () => {
    const r = Schema.safeParse({ gender: "alien" });
    expect(r.success).toBe(false);
  });

  it("rejects unknown employmentStatus enum", () => {
    const r = Schema.safeParse({ employmentStatus: "freelancer" });
    expect(r.success).toBe(false);
  });

  it("rejects unknown jobTenure enum", () => {
    const r = Schema.safeParse({ jobTenure: "5_years" });
    expect(r.success).toBe(false);
  });

  it("rejects industry longer than 64 chars", () => {
    const r = Schema.safeParse({ industry: "x".repeat(65) });
    expect(r.success).toBe(false);
  });

  it("rejects bundesland with foreign-country code", () => {
    expect(Schema.safeParse({ bundesland: "AT-9" }).success).toBe(false);
    expect(Schema.safeParse({ bundesland: "BY" }).success).toBe(false);
    expect(Schema.safeParse({ bundesland: "DE-XX" }).success).toBe(false);
  });

  it("accepts all 16 valid Bundesländer codes", () => {
    const codes = [
      "DE-BW","DE-BY","DE-BE","DE-BB","DE-HB","DE-HH","DE-HE","DE-MV",
      "DE-NI","DE-NW","DE-RP","DE-SL","DE-SN","DE-ST","DE-SH","DE-TH",
    ];
    for (const c of codes) {
      expect(Schema.safeParse({ bundesland: c }).success).toBe(true);
    }
  });

  it("rejects profession longer than 80 chars (legacy field, still validated)", () => {
    const r = Schema.safeParse({ profession: "x".repeat(81) });
    expect(r.success).toBe(false);
  });

  it("rejects city longer than 80 chars", () => {
    const r = Schema.safeParse({ city: "x".repeat(81) });
    expect(r.success).toBe(false);
  });

  it("rejects shiftWork as non-boolean string", () => {
    const r = Schema.safeParse({ shiftWork: "yes" });
    expect(r.success).toBe(false);
  });
});
