/**
 * Zod schemas for purchase API routes.
 *
 * Used at the API boundary for input validation and response typing.
 * Import the schema to safeParse() and the inferred type for TypeScript.
 */

import { z } from 'zod';
import { redemptionStatus } from '@/lib/enums/redemption-status';

// ---------------------------------------------------------------------------
// Shared field schemas
// ---------------------------------------------------------------------------

const uuidSchema = z.uuid('Must be a valid UUID');
const idempotencyKeySchema = z.string().min(8).max(128);

// ---------------------------------------------------------------------------
// POST /api/purchases (registered user purchase)
// ---------------------------------------------------------------------------

export const createPurchaseBodySchema = z.object({
  dealId: uuidSchema,
  paymentMethodId: uuidSchema,
  idempotencyKey: idempotencyKeySchema,
  /** CSRF token - validated server-side against session */
  csrfToken: z.string().min(1).optional(),
});

export type CreatePurchaseBody = z.infer<typeof createPurchaseBodySchema>;

export const createPurchaseResponseSchema = z.object({
  ok: z.literal(true),
  purchaseId: uuidSchema,
  qrPngUrl: z.url(),
});

export type CreatePurchaseResponse = z.infer<typeof createPurchaseResponseSchema>;

// ---------------------------------------------------------------------------
// POST /api/purchases/guest (guest purchase)
// ---------------------------------------------------------------------------

const emailSchema = z.email('Invalid email address').trim().max(254);
const phoneSchema = z
  .string()
  .trim()
  .regex(/^\+?[0-9]{9,15}$/, 'Invalid phone number format');

export const createGuestPurchaseBodySchema = z.object({
  guestEmail: emailSchema,
  guestPhone: phoneSchema,
  dealId: uuidSchema,
  idempotencyKey: idempotencyKeySchema,
  recoverySecret: z.string().regex(/^[a-f0-9]{64}$/),
});

export type CreateGuestPurchaseBody = z.infer<typeof createGuestPurchaseBodySchema>;

export const createGuestPurchaseResponseSchema = z.object({
  ok: z.literal(true),
  purchaseId: uuidSchema,
  /**
   * Plaintext guest access token — required to view the confirmation page.
   * Re-derived on idempotent replay from caller-held recovery secret.
   */
  guestAccessToken: z.string().regex(/^[a-f0-9]{64}$/),
});

export type CreateGuestPurchaseResponse = z.infer<typeof createGuestPurchaseResponseSchema>;

/**
 * Query param schema for /purchases/[id]/confirmation `?t=` (BUG-2 IDOR fix).
 * 32-byte token rendered as 64 lowercase hex characters.
 */
export const guestAccessTokenQuerySchema = z.string().regex(/^[a-f0-9]{64}$/);

// ---------------------------------------------------------------------------
// POST /api/checkout/intent-guest (guest checkout PaymentIntent creation)
// ---------------------------------------------------------------------------

export const checkoutIntentGuestBodySchema = z.object({
  purchaseId: uuidSchema,
  guestAccessToken: guestAccessTokenQuerySchema,
});

export type CheckoutIntentGuestBody = z.infer<typeof checkoutIntentGuestBodySchema>;

// ---------------------------------------------------------------------------
// GET /api/purchases (list for authenticated user)
// ---------------------------------------------------------------------------

const purchaseStatusSchema = redemptionStatus.schema;

/** One purchased unit's voucher — powers per-unit QR rendering for quantity>1 lines. */
export const purchaseVoucherSummarySchema = z.object({
  voucherId: z.string(),
  unitIndex: z.number().int().nonnegative(),
  state: z.string(),
  qrPngUrl: z.url().nullable(),
  expiresAt: z.iso.datetime().nullable(),
  redeemedAt: z.iso.datetime().nullable(),
});

export const purchaseSummarySchema = z.object({
  id: uuidSchema,
  dealId: uuidSchema,
  vendorId: uuidSchema,
  dealTitle: z.string(),
  businessName: z.string(),
  qrPngUrl: z.url().nullable(),
  dealImageUrl: z.string().nullable(),
  amountPaid: z.string(),
  originalPrice: z.string(),
  quantity: z.number().int().positive(),
  redemptionStatus: purchaseStatusSchema,
  paymentStatus: z.string(),
  expiresAt: z.iso.datetime(),
  redeemedAt: z.iso.datetime().nullable(),
  createdAt: z.iso.datetime(),
  reviewEligible: z.boolean(),
  /** One entry per purchased unit, ordered by unitIndex ASC. Additive — qty=1 still has qrPngUrl above. */
  vouchers: z.array(purchaseVoucherSummarySchema).optional(),
});

export type PurchaseSummary = z.infer<typeof purchaseSummarySchema>;

export const listPurchasesResponseSchema = z.object({
  ok: z.literal(true),
  active: z.array(purchaseSummarySchema),
  history: z.array(purchaseSummarySchema),
  totalSavings: z.number().nonnegative(),
  businessCount: z.number().int().nonnegative(),
});

export type ListPurchasesResponse = z.infer<typeof listPurchasesResponseSchema>;

// ---------------------------------------------------------------------------
// GET /api/purchases/[id] (purchase detail)
// ---------------------------------------------------------------------------

export const purchaseDetailSchema = z.object({
  id: uuidSchema,
  dealId: uuidSchema,
  vendorId: uuidSchema,
  quantity: z.number().int().positive(),
  amountPaid: z.string(),
  commissionAmount: z.string(),
  vendorAmount: z.string(),
  paymentStatus: z.string(),
  redemptionStatus: purchaseStatusSchema,
  qrPngUrl: z.url().nullable(),
  redeemedAt: z.iso.datetime().nullable(),
  expiresAt: z.iso.datetime(),
  cancelledAt: z.iso.datetime().nullable(),
  reviewEligible: z.boolean(),
  createdAt: z.iso.datetime(),
});

export type PurchaseDetail = z.infer<typeof purchaseDetailSchema>;

// ---------------------------------------------------------------------------
// POST /api/purchases/[id]/redeem (vendor QR scan)
// ---------------------------------------------------------------------------

export const redeemBodySchema = z.object({
  token: z.string().min(1).max(2048),
  /** CSRF token */
  csrfToken: z.string().min(1).optional(),
});

export type RedeemBody = z.infer<typeof redeemBodySchema>;

// ---------------------------------------------------------------------------
// POST /api/purchases/[id]/messages (purchase messaging)
// ---------------------------------------------------------------------------

export const sendPurchaseMessageBodySchema = z.object({
  body: z.string().trim().min(1).max(2000),
  csrfToken: z.string().min(1).optional(),
});

export type SendPurchaseMessageBody = z.infer<typeof sendPurchaseMessageBodySchema>;

export const purchaseMessageSchema = z.object({
  id: uuidSchema,
  purchaseId: uuidSchema,
  senderType: z.enum(['USER', 'VENDOR']),
  senderId: uuidSchema,
  body: z.string(),
  readAt: z.iso.datetime().nullable(),
  createdAt: z.iso.datetime(),
});

export type PurchaseMessage = z.infer<typeof purchaseMessageSchema>;
