/**
 * Quotation Validator Tests
 *
 * Tests for all Zod schemas:
 * - createQuotationSchema — create input validation
 * - updateQuotationSchema — partial update validation
 * - quotationItemSchema — line item validation
 * - quotationFilterSchema — list filter validation
 * - manualPaymentSchema — manual payment input validation
 */

import {
  createQuotationSchema,
  updateQuotationSchema,
  quotationItemSchema,
  quotationFilterSchema,
} from "@/lib/validators/quotations.validator";
import { manualPaymentSchema } from "@/lib/validators/quotation-payments.validator";

// ═══════════════════════════════════════════════════════════════════════
// createQuotationSchema
// ═══════════════════════════════════════════════════════════════════════

describe("createQuotationSchema", () => {
  it("accepts minimal valid input with defaults", () => {
    const result = createQuotationSchema.safeParse({ title: "Test Quote" });
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.currency).toBe("QAR");
      expect(result.data.taxRate).toBe(0);
      expect(result.data.discountRate).toBe(0);
      expect(result.data.items).toEqual([]);
      expect(result.data.sendImmediately).toBe(true);
    }
  });

  it("accepts full valid input", () => {
    const result = createQuotationSchema.safeParse({
      title: "Web Design",
      customerId: "c1",
      notes: "Important project",
      currency: "SAR",
      taxRate: 15,
      discountRate: 10,
      validUntil: "2026-04-30T00:00:00.000Z",
      items: [
        { description: "Landing Page", quantity: 3, unitPrice: 500 },
      ],
      sendImmediately: false,
    });
    expect(result.success).toBe(true);
  });

  it("rejects empty title", () => {
    const result = createQuotationSchema.safeParse({
      title: "",
      items: [],
    });
    expect(result.success).toBe(false);
  });

  it("rejects title exceeding 200 chars", () => {
    const result = createQuotationSchema.safeParse({
      title: "a".repeat(201),
      items: [],
    });
    expect(result.success).toBe(false);
  });

  it("rejects taxRate > 100", () => {
    const result = createQuotationSchema.safeParse({
      title: "Test",
      taxRate: 101,
    });
    expect(result.success).toBe(false);
  });

  it("rejects negative discountRate", () => {
    const result = createQuotationSchema.safeParse({
      title: "Test",
      discountRate: -5,
    });
    expect(result.success).toBe(false);
  });

  it("rejects invalid currency length", () => {
    const result = createQuotationSchema.safeParse({
      title: "Test",
      currency: "US",
    });
    expect(result.success).toBe(false);
  });

  it("rejects invalid datetime format for validUntil", () => {
    const result = createQuotationSchema.safeParse({
      title: "Test",
      validUntil: "not-a-date",
    });
    expect(result.success).toBe(false);
  });

  it("rejects notes exceeding 2000 chars", () => {
    const result = createQuotationSchema.safeParse({
      title: "Test",
      notes: "x".repeat(2001),
    });
    expect(result.success).toBe(false);
  });
});

// ═══════════════════════════════════════════════════════════════════════
// updateQuotationSchema
// ═══════════════════════════════════════════════════════════════════════

describe("updateQuotationSchema", () => {
  it("accepts empty object (all fields optional)", () => {
    const result = updateQuotationSchema.safeParse({});
    expect(result.success).toBe(true);
  });

  it("accepts partial updates", () => {
    const result = updateQuotationSchema.safeParse({
      title: "Updated",
      taxRate: 10,
    });
    expect(result.success).toBe(true);
  });

  it("accepts all valid status values", () => {
    const statuses = [
      "DRAFT",
      "SENT",
      "VIEWED",
      "ACCEPTED",
      "DECLINED",
      "EXPIRED",
      "CANCELLED",
    ];
    for (const status of statuses) {
      const result = updateQuotationSchema.safeParse({ status });
      expect(result.success).toBe(true);
    }
  });

  it("rejects invalid status", () => {
    const result = updateQuotationSchema.safeParse({ status: "INVALID" });
    expect(result.success).toBe(false);
  });

  it("allows nullable customerId", () => {
    const result = updateQuotationSchema.safeParse({ customerId: null });
    expect(result.success).toBe(true);
  });

  it("allows nullable validUntil", () => {
    const result = updateQuotationSchema.safeParse({ validUntil: null });
    expect(result.success).toBe(true);
  });
});

// ═══════════════════════════════════════════════════════════════════════
// quotationItemSchema
// ═══════════════════════════════════════════════════════════════════════

describe("quotationItemSchema", () => {
  it("accepts valid item", () => {
    const result = quotationItemSchema.safeParse({
      description: "Web Design",
      quantity: 2,
      unitPrice: 500,
    });
    expect(result.success).toBe(true);
  });

  it("rejects empty description", () => {
    const result = quotationItemSchema.safeParse({
      description: "",
      quantity: 1,
      unitPrice: 100,
    });
    expect(result.success).toBe(false);
  });

  it("rejects zero quantity", () => {
    const result = quotationItemSchema.safeParse({
      description: "Test",
      quantity: 0,
      unitPrice: 100,
    });
    expect(result.success).toBe(false);
  });

  it("rejects negative quantity", () => {
    const result = quotationItemSchema.safeParse({
      description: "Test",
      quantity: -1,
      unitPrice: 100,
    });
    expect(result.success).toBe(false);
  });

  it("accepts zero unitPrice", () => {
    const result = quotationItemSchema.safeParse({
      description: "Free item",
      quantity: 1,
      unitPrice: 0,
    });
    expect(result.success).toBe(true);
  });

  it("rejects negative unitPrice", () => {
    const result = quotationItemSchema.safeParse({
      description: "Test",
      quantity: 1,
      unitPrice: -50,
    });
    expect(result.success).toBe(false);
  });

  it("rejects description exceeding 500 chars", () => {
    const result = quotationItemSchema.safeParse({
      description: "a".repeat(501),
      quantity: 1,
      unitPrice: 100,
    });
    expect(result.success).toBe(false);
  });

  it("defaults quantity to 1 and unitPrice to 0", () => {
    const result = quotationItemSchema.safeParse({
      description: "Test",
    });
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.quantity).toBe(1);
      expect(result.data.unitPrice).toBe(0);
    }
  });
});

// ═══════════════════════════════════════════════════════════════════════
// quotationFilterSchema
// ═══════════════════════════════════════════════════════════════════════

describe("quotationFilterSchema", () => {
  it("provides defaults for all fields", () => {
    const result = quotationFilterSchema.safeParse({});
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.page).toBe(1);
      expect(result.data.limit).toBe(20);
      expect(result.data.sortBy).toBe("createdAt");
      expect(result.data.sortOrder).toBe("desc");
    }
  });

  it("accepts valid sort options", () => {
    const result = quotationFilterSchema.safeParse({
      sortBy: "total",
      sortOrder: "asc",
    });
    expect(result.success).toBe(true);
  });

  it("rejects limit > 100", () => {
    const result = quotationFilterSchema.safeParse({ limit: 101 });
    expect(result.success).toBe(false);
  });

  it("rejects page < 1", () => {
    const result = quotationFilterSchema.safeParse({ page: 0 });
    expect(result.success).toBe(false);
  });
});

// ═══════════════════════════════════════════════════════════════════════
// manualPaymentSchema
// ═══════════════════════════════════════════════════════════════════════

describe("manualPaymentSchema", () => {
  it("accepts valid manual payment", () => {
    const result = manualPaymentSchema.safeParse({
      amount: 250.50,
      method: "MANUAL_CASH",
    });
    expect(result.success).toBe(true);
  });

  it("accepts all valid payment methods", () => {
    const methods = [
      "MANUAL_CASH",
      "MANUAL_BANK_TRANSFER",
      "MANUAL_CHECK",
      "MANUAL_OTHER",
    ];
    for (const method of methods) {
      const result = manualPaymentSchema.safeParse({ amount: 100, method });
      expect(result.success).toBe(true);
    }
  });

  it("rejects zero amount", () => {
    const result = manualPaymentSchema.safeParse({
      amount: 0,
      method: "MANUAL_CASH",
    });
    expect(result.success).toBe(false);
  });

  it("rejects negative amount", () => {
    const result = manualPaymentSchema.safeParse({
      amount: -100,
      method: "MANUAL_CASH",
    });
    expect(result.success).toBe(false);
  });

  it("rejects invalid method", () => {
    const result = manualPaymentSchema.safeParse({
      amount: 100,
      method: "STRIPE",
    });
    expect(result.success).toBe(false);
  });

  it("accepts optional reference and notes", () => {
    const result = manualPaymentSchema.safeParse({
      amount: 100,
      method: "MANUAL_BANK_TRANSFER",
      reference: "TXN-12345",
      manualNotes: "Bank transfer confirmed",
    });
    expect(result.success).toBe(true);
  });

  it("rejects reference exceeding 200 chars", () => {
    const result = manualPaymentSchema.safeParse({
      amount: 100,
      method: "MANUAL_CASH",
      reference: "a".repeat(201),
    });
    expect(result.success).toBe(false);
  });

  it("rejects notes exceeding 1000 chars", () => {
    const result = manualPaymentSchema.safeParse({
      amount: 100,
      method: "MANUAL_CASH",
      manualNotes: "a".repeat(1001),
    });
    expect(result.success).toBe(false);
  });

  it("accepts optional paidAt datetime", () => {
    const result = manualPaymentSchema.safeParse({
      amount: 100,
      method: "MANUAL_CASH",
      paidAt: "2026-03-24T10:00:00.000Z",
    });
    expect(result.success).toBe(true);
  });
});
