import { z } from "zod";

export const DOMESTIC_QUESTION_TYPES = [
  "single_choice",
  "multi_choice",
  "yes_no",
  "rating",
  "number",
  "short_text",
] as const;

export const DOMESTIC_SENSITIVITIES = ["standard", "personal", "sensitive"] as const;

export const DOMESTIC_CONDITION_TYPES = [
  "always",
  "equals",
  "not_equals",
  "any_of",
  "includes",
  "gte",
  "lte",
] as const;

export const DOMESTIC_EDGE_TYPES = ["unlock", "boost", "suppress", "terminate"] as const;

export const DOMESTIC_CODE_PATTERN = /^DOM-\d{4,6}$/;

const optionSchema = z.object({
  value: z.string().trim().max(64).optional(),
  label: z.string().trim().min(1, "Option text is required").max(200),
});

export const domesticContentSchema = z
  .object({
    type: z.enum(DOMESTIC_QUESTION_TYPES),
    prompt: z.string().trim().min(3, "Question text is required").max(1000),
    helpText: z
      .string()
      .trim()
      .max(1000)
      .optional()
      .transform((v) => (v ? v : null)),
    purpose: z
      .string()
      .trim()
      .max(500)
      .optional()
      .transform((v) => (v ? v : null)),
    options: z.array(optionSchema).max(30).optional(),
    min: z.number().int().optional().nullable(),
    max: z.number().int().optional().nullable(),
    minLabel: z.string().trim().max(60).optional(),
    maxLabel: z.string().trim().max(60).optional(),
  })
  .superRefine((v, ctx) => {
    if (v.type === "single_choice" || v.type === "multi_choice") {
      if (!v.options || v.options.length < 2) {
        ctx.addIssue({
          code: "custom",
          path: ["options"],
          message: "Add at least two options",
        });
      }
    }
    if (v.type === "rating") {
      const min = v.min ?? 1;
      const max = v.max ?? 5;
      if (min < 0 || max > 10 || max <= min) {
        ctx.addIssue({
          code: "custom",
          path: ["max"],
          message: "Rating scale must be between 0 and 10 with max > min",
        });
      }
    }
    if (v.type === "number" && v.min != null && v.max != null && v.max < v.min) {
      ctx.addIssue({
        code: "custom",
        path: ["max"],
        message: "Maximum must be greater than minimum",
      });
    }
  });

export type DomesticContentInput = z.input<typeof domesticContentSchema>;

export const domesticMetaSchema = z.object({
  categoryId: z.string().uuid("Choose a category"),
  sensitivity: z.enum(DOMESTIC_SENSITIVITIES),
  isEntry: z.boolean(),
  rotationWeight: z.number().int().min(0).max(1000),
});

export type DomesticMetaInput = z.input<typeof domesticMetaSchema>;

export const createDomesticQuestionSchema = z.object({
  code: z
    .string()
    .trim()
    .toUpperCase()
    .regex(DOMESTIC_CODE_PATTERN, "Code must look like DOM-0180")
    .optional()
    .or(z.literal("").transform(() => undefined)),
  meta: domesticMetaSchema,
  content: domesticContentSchema,
});

export type CreateDomesticQuestionInput = z.input<
  typeof createDomesticQuestionSchema
>;

export const domesticEdgeSchema = z.object({
  questionId: z.string().uuid(),
  conditionType: z.enum(DOMESTIC_CONDITION_TYPES),
  conditionValue: z.union([z.string().max(64), z.number()]).optional(),
  conditionValues: z.array(z.string().max(64)).max(30).optional(),
  toQuestionId: z.string().uuid().optional().nullable(),
  edgeType: z.enum(DOMESTIC_EDGE_TYPES),
  priority: z.number().int().min(0).max(10000),
});

export type DomesticEdgeInput = z.input<typeof domesticEdgeSchema>;

export const domesticCategorySchema = z.object({
  name: z.string().trim().min(2, "Name is required").max(120),
  description: z
    .string()
    .trim()
    .max(500)
    .optional()
    .transform((v) => (v ? v : null)),
});

export const domesticStatusSchema = z.object({
  questionId: z.string().uuid(),
  status: z.enum(["published", "paused", "retired"]),
});
