/**
 * Common Domain - Schemas
 *
 * Shared validation primitives used across all domains.
 */

import { z } from "zod";

export const emailSchema = z
  .string()
  .email("Please enter a valid email address")
  .toLowerCase()
  .trim();

export const passwordSchema = z
  .string()
  .min(8, "Password must be at least 8 characters")
  .regex(/[A-Z]/, "Password must contain at least one uppercase letter")
  .regex(/[a-z]/, "Password must contain at least one lowercase letter")
  .regex(/[0-9]/, "Password must contain at least one number")
  .regex(/[^A-Za-z0-9]/, "Password must contain at least one special character");

export const nameSchema = z.string().min(1, "Name is required").max(100, "Name must be less than 100 characters").trim();

export const phoneSchema = z
  .string()
  .regex(/^[+]?[0-9\s\-()]{7,20}$/u, "Please enter a valid phone number")
  .trim();

export const countryCodeSchema = z.string().length(2, "Country code must be 2 characters");
export const currencyCodeSchema = z.string().length(3, "Currency code must be 3 characters");

export const timestampSchema = z.string().datetime("Invalid timestamp format");
export const dateSchema = z.string().date("Invalid date format");

export const moneyAmountSchema = z.number().int().nonnegative("Amount must be non-negative");
export const percentageSchema = z.number().min(0).max(100, "Percentage must be between 0 and 100");

export const genderEnum = z.enum(["male", "female", "other"]);
export const statusEnum = z.enum(["active", "inactive", "pending", "suspended"]);
export const priorityEnum = z.enum(["low", "medium", "high", "urgent"]);
export const categoryEnum = z.enum(["technical", "billing", "account", "general"]);

export const billingCycleEnum = z.enum(["Monthly", "Quarterly", "Annually", "Onetime", "Free"]);
export const subscriptionBillingCycleEnum = z.enum([
  "Monthly",
  "Quarterly",
  "Semi-Annually",
  "Annually",
  "Biennially",
  "Triennially",
  "One-time",
  "Free",
]);

// ============================================================================
// Salesforce and SOQL Validation Schemas
// ============================================================================

/**
 * Schema for validating Salesforce Account IDs
 */
export const salesforceAccountIdSchema = z.string().min(1, "Salesforce AccountId is required");

/**
 * Schema for validating Salesforce IDs (15 or 18 characters)
 */
export const salesforceIdSchema = z
  .string()
  .regex(/^[a-zA-Z0-9]{15,18}$/, "Invalid Salesforce ID format")
  .trim();

/**
 * Schema for validating non-empty strings
 */
export const nonEmptyStringSchema = z.string().min(1, "Value cannot be empty").trim();

/**
 * Schema for validating SOQL field names
 */
export const soqlFieldNameSchema = z.string().trim().regex(/^[A-Za-z0-9_.]+$/, "Invalid SOQL field name");

// ============================================================================
// API Response Schemas
// ============================================================================

/**
 * Schema for successful API responses
 * Usage: apiSuccessResponseSchema(yourDataSchema)
 */
export const apiSuccessResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>
  z.object({
    success: z.literal(true),
    data: dataSchema,
  });

/**
 * Schema for error API responses
 */
export const apiErrorResponseSchema = z.object({
  success: z.literal(false),
  error: z.object({
    code: z.string(),
    message: z.string(),
    details: z.unknown().optional(),
  }),
});

/**
 * Discriminated union schema for API responses
 * Usage: apiResponseSchema(yourDataSchema)
 */
export const apiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>
  z.discriminatedUnion("success", [
    apiSuccessResponseSchema(dataSchema),
    apiErrorResponseSchema,
  ]);

// ============================================================================
// Pagination Schemas
// ============================================================================

/**
 * Schema for pagination query parameters
 */
export const paginationParamsSchema = z.object({
  page: z.coerce.number().int().positive().optional().default(1),
  limit: z.coerce.number().int().positive().max(100).optional().default(20),
  offset: z.coerce.number().int().nonnegative().optional(),
});

/**
 * Schema for paginated response data
 */
export const paginatedResponseSchema = <T extends z.ZodTypeAny>(itemSchema: T) =>
  z.object({
    items: z.array(itemSchema),
    total: z.number().int().nonnegative(),
    page: z.number().int().positive(),
    limit: z.number().int().positive(),
    hasMore: z.boolean(),
  });

// ============================================================================
// Query Parameter Schemas
// ============================================================================

/**
 * Schema for common filter parameters
 */
export const filterParamsSchema = z.object({
  search: z.string().optional(),
  sortBy: z.string().optional(),
  sortOrder: z.enum(["asc", "desc"]).optional(),
});

/**
 * Combined query params schema (pagination + filters)
 */
export const queryParamsSchema = paginationParamsSchema.merge(filterParamsSchema);
