import { z } from "zod";
import {
  nonNegativeIntFromForm,
  nonNegativeNumberFromForm,
  positiveNumberFromForm,
  nullableIntIdFromForm,
  booleanFromForm,
  isoDateString,
  DocumentSectionSchema,
} from "./common";

// Limits are DB-aligned: description VarChar(500), unit VarChar(20);
// item_description is Text with the app-level 8000 cap used elsewhere.
const QuotationItemSchema = z.object({
  description: z.string().max(500).nullish(),
  item_description: z.string().max(8000).nullish(),
  quantity: positiveNumberFromForm.default(1),
  unit: z.string().max(20).nullish(),
  unit_price: nonNegativeNumberFromForm.default(0),
  is_included_in_total: booleanFromForm.optional().default(true),
  // Int column — a float position would 500 at Prisma.
  position: nonNegativeIntFromForm.optional(),
});

// Shared with issued orders (scope_sections ≡ issued_order_sections).
const ScopeSectionSchema = DocumentSectionSchema;

// NOTE: no top-level `.default()`s here — `UpdateQuotationSchema` derives from
// this schema via `.partial()`, and Zod 4 still applies a field default when
// the key is absent, which would silently inject status/currency/language
// resets into every update payload. Create-time defaults live in
// `createOffer` (service) instead.
export const CreateQuotationSchema = z.object({
  // DB: quotations.quotation_number VarChar(50).
  quotation_number: z.string().max(50).nullish(),
  // DB column is VarChar(100) — a longer value would 500 at Prisma.
  project_code: z.string().max(100).nullish(),
  customer_id: nullableIntIdFromForm.nullish(),
  created_at: isoDateString.nullish(),
  valid_until: isoDateString.nullish(),
  currency: z.string().max(20).optional(),
  language: z.string().max(20).optional(),
  status: z.enum(["draft", "active", "ordered", "invalidated"]).optional(),
  scope_title: z.string().max(255).nullish(),
  scope_description: z.string().max(8000).nullish(),
  items: z.array(QuotationItemSchema).optional(),
  sections: z.array(ScopeSectionSchema).optional(),
});

// Update = partial create MINUS the number: quotation numbers are immutable
// (assigned by the sequence on finalize), so the field is stripped before it
// can ever reach the service.
export const UpdateQuotationSchema = CreateQuotationSchema.partial().omit({
  quotation_number: true,
});

export type CreateQuotationInput = z.infer<typeof CreateQuotationSchema>;
export type UpdateQuotationInput = z.infer<typeof UpdateQuotationSchema>;
