import { z } from "zod"
import { InvoiceDiscount, InvoiceStatus } from "@garage/api"

const relationFieldSchema = z
    .object({ value: z.string(), label: z.string() })
    .nullable()

const requiredDateSchema = z
    .string()
    .min(1, "This field is required")
    .date("Enter a valid date")

const invoicePartItemSchema = z.object({
    part_id: z.number(),
    title: z.string(),
    quantity: z.number().min(1),
    rate: z.number().min(0),
    discount_amount: z.number().min(0).optional(),
    description: z.string().optional(),
})

const invoiceServiceItemSchema = z.object({
    service_id: z.number(),
    title: z.string(),
    quantity: z.number().min(1),
    rate: z.number().min(0),
    discount_amount: z.number().min(0).optional(),
    description: z.string().optional(),
})

const invoiceExpenseItemSchema = z.object({
    expense_id: z.number(),
    title: z.string(),
    quantity: z.number().min(1),
    rate: z.number().min(0),
    discount_amount: z.number().min(0).optional(),
    description: z.string().optional(),
})

const invoiceFormSchema = z.object({
    // ── Required fields ──
    subject: z.string().trim().min(1, "Subject is required").max(255, "Subject must be at most 255 characters"),

    // ── Relations ──
    customer: relationFieldSchema,
    vehicle: relationFieldSchema,
    department: relationFieldSchema,
    estimate: relationFieldSchema,
    payment_terms: relationFieldSchema,
    invoice_sequence: relationFieldSchema,
    payment_mode: relationFieldSchema,
    insurer: relationFieldSchema,
    invoice_to: relationFieldSchema,

    // ── Optional fields ──
    invoice_number: z.string().trim().min(1, "Invoice number is required").max(255, "Invoice number must be at most 255 characters"),
    invoice_title: z.string().optional(),
    invoice_date: requiredDateSchema,
    due_date: requiredDateSchema,
    status: z.enum(InvoiceStatus).optional(),
    kms_in: z.coerce.number().optional(),
    has_insurance: z.boolean().default(false),
    discount: z.enum(InvoiceDiscount).optional(),
    discount_amount: z.coerce.number().min(0).optional(),
    tax: relationFieldSchema,
    deposit_to: z.string().optional(),
    notes: z.string().optional(),
    terms_and_conditions: z.string().optional(),

    // ── Line items ──
    parts: z.array(invoicePartItemSchema).optional(),
    services: z.array(invoiceServiceItemSchema).optional(),
    expense_items: z.array(invoiceExpenseItemSchema).optional(),
}).superRefine((values, ctx) => {
    if (values.invoice_date && values.due_date) {
        const invoiceDate = new Date(values.invoice_date)
        const dueDate = new Date(values.due_date)

        if (!Number.isNaN(invoiceDate.getTime()) && !Number.isNaN(dueDate.getTime()) && dueDate < invoiceDate) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                path: ["due_date"],
                message: "Due date must be on or after invoice date",
            })
        }
    }
})

type InvoiceFormValues = z.infer<typeof invoiceFormSchema>
type InvoicePartItem = z.infer<typeof invoicePartItemSchema>
type InvoiceServiceItem = z.infer<typeof invoiceServiceItemSchema>
type InvoiceExpenseItem = z.infer<typeof invoiceExpenseItemSchema>

export { invoiceFormSchema, relationFieldSchema, invoicePartItemSchema, invoiceServiceItemSchema, invoiceExpenseItemSchema }
export type { InvoiceFormValues, InvoicePartItem, InvoiceServiceItem, InvoiceExpenseItem }
