/**
 * Orders Domain - Schemas
 * 
 * Zod schemas for runtime validation of order data.
 */

import { z } from "zod";
import { apiSuccessResponseSchema } from "../common";

// ============================================================================
// Enum Value Arrays (for Zod schemas)
// ============================================================================
// These arrays are used by Zod schemas for validation.
// For type-safe constants, see contract.ts (ACCESS_MODE, ACTIVATION_TYPE, SIM_TYPE)

const ACCESS_MODE_VALUES = ["IPoE-BYOR", "IPoE-HGW", "PPPoE"] as const;
const ACTIVATION_TYPE_VALUES = ["Immediate", "Scheduled"] as const;
const SIM_TYPE_VALUES = ["eSIM", "Physical SIM"] as const;
const PORTING_GENDER_VALUES = ["Male", "Female", "Corporate/Other"] as const;

// ============================================================================
// Order Item Summary Schema
// ============================================================================

export const orderItemSummarySchema = z.object({
  productName: z.string().optional(),
  name: z.string().optional(),
  sku: z.string().optional(),
  productId: z.string().optional(),
  status: z.string().optional(),
  billingCycle: z.string().optional(),
  itemClass: z.string().optional(),
  quantity: z.number().int().min(0).optional(),
  unitPrice: z.number().optional(),
  totalPrice: z.number().optional(),
  isBundledAddon: z.boolean().optional(),
  bundledAddonId: z.string().optional(),
});

// ============================================================================
// Order Item Details Schema
// ============================================================================

export const orderItemDetailsSchema = z.object({
  id: z.string(),
  orderId: z.string(),
  quantity: z.number().int().min(1),
  unitPrice: z.number().optional(),
  totalPrice: z.number().optional(),
  billingCycle: z.string().optional(),
  product: z.object({
    id: z.string().optional(),
    name: z.string().optional(),
    sku: z.string().optional(),
    itemClass: z.string().optional(),
    whmcsProductId: z.string().optional(),
    internetOfferingType: z.string().optional(),
    internetPlanTier: z.string().optional(),
    vpnRegion: z.string().optional(),
    isBundledAddon: z.boolean().optional(),
    bundledAddonId: z.string().optional(),
  }).optional(),
});

// ============================================================================
// Order Summary Schema
// ============================================================================

export const orderSummarySchema = z.object({
  id: z.string(),
  orderNumber: z.string(),
  status: z.string(),
  orderType: z.string().optional(),
  effectiveDate: z.string(), // IsoDateTimeString
  totalAmount: z.number().optional(),
  createdDate: z.string(), // IsoDateTimeString
  lastModifiedDate: z.string(), // IsoDateTimeString
  whmcsOrderId: z.string().optional(),
  activationStatus: z.string().optional(),
  itemsSummary: z.array(orderItemSummarySchema),
});

// ============================================================================
// Order Details Schema
// ============================================================================

export const orderDetailsSchema = orderSummarySchema.extend({
  accountId: z.string().optional(),
  accountName: z.string().optional(),
  pricebook2Id: z.string().optional(),
  activationType: z.string().optional(),
  activationStatus: z.string().optional(),
  activationScheduledAt: z.string().optional(), // IsoDateTimeString
  activationErrorCode: z.string().optional(),
  activationErrorMessage: z.string().optional(),
  activatedDate: z.string().optional(), // IsoDateTimeString
  items: z.array(orderItemDetailsSchema),
});

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

/**
 * Schema for order query parameters
 */
export const orderQueryParamsSchema = z.object({
  page: z.coerce.number().int().positive().optional(),
  limit: z.coerce.number().int().positive().max(100).optional(),
  status: z.string().optional(),
  orderType: z.string().optional(),
});

// ============================================================================
// Order Creation Schemas
// ============================================================================

const orderConfigurationsAddressSchema = z.object({
  street: z.string().nullable().optional(),
  streetLine2: z.string().nullable().optional(),
  city: z.string().nullable().optional(),
  state: z.string().nullable().optional(),
  postalCode: z.string().nullable().optional(),
  country: z.string().nullable().optional(),
});

export const orderConfigurationsSchema = z.object({
  activationType: z.enum(ACTIVATION_TYPE_VALUES).optional(),
  scheduledAt: z.string().optional(),
  accessMode: z.enum(ACCESS_MODE_VALUES).optional(),
  simType: z.enum(SIM_TYPE_VALUES).optional(),
  eid: z.string().optional(),
  isMnp: z.string().optional(),
  mnpNumber: z.string().optional(),
  mnpExpiry: z.string().optional(),
  mnpPhone: z.string().optional(),
  mvnoAccountNumber: z.string().optional(),
  portingLastName: z.string().optional(),
  portingFirstName: z.string().optional(),
  portingLastNameKatakana: z.string().optional(),
  portingFirstNameKatakana: z.string().optional(),
  portingGender: z.enum(PORTING_GENDER_VALUES).optional(),
  portingDateOfBirth: z.string().optional(),
  address: orderConfigurationsAddressSchema.optional(),
});

/**
 * Schema for raw checkout selections (typically derived from UI/query params)
 */
export const orderSelectionsSchema = z
  .object({
    plan: z.string().optional(),
    planId: z.string().optional(),
    planSku: z.string().optional(),
    planIdSku: z.string().optional(),
    installationSku: z.string().optional(),
    activationFeeSku: z.string().optional(),
    activationSku: z.string().optional(),
    addonSku: z.string().optional(),
    addons: z.string().optional(),
    accessMode: z.enum(ACCESS_MODE_VALUES).optional(),
    activationType: z.enum(ACTIVATION_TYPE_VALUES).optional(),
    scheduledAt: z.string().optional(),
    simType: z.enum(SIM_TYPE_VALUES).optional(),
    eid: z.string().optional(),
    isMnp: z.string().optional(),
    mnpNumber: z.string().optional(),
    mnpExpiry: z.string().optional(),
    mnpPhone: z.string().optional(),
    mvnoAccountNumber: z.string().optional(),
    portingLastName: z.string().optional(),
    portingFirstName: z.string().optional(),
    portingLastNameKatakana: z.string().optional(),
    portingFirstNameKatakana: z.string().optional(),
    portingGender: z.enum(PORTING_GENDER_VALUES).optional(),
    portingDateOfBirth: z.string().optional(),
    address: z
      .object({
        street: z.string().optional(),
        streetLine2: z.string().optional(),
        city: z.string().optional(),
        state: z.string().optional(),
        postalCode: z.string().optional(),
        country: z.string().optional(),
      })
      .optional(),
  })
  .passthrough();

export type OrderSelections = z.infer<typeof orderSelectionsSchema>;

const baseCreateOrderSchema = z.object({
  orderType: z.enum(["Internet", "SIM", "VPN", "Other"]),
  skus: z.array(z.string()),
  configurations: orderConfigurationsSchema.optional(),
});

export const createOrderRequestSchema = baseCreateOrderSchema;

export const orderBusinessValidationSchema =
  baseCreateOrderSchema
    .extend({
      userId: z.string().uuid(),
      opportunityId: z.string().optional(),
    })
    .refine(
      (data) => {
        if (data.orderType === "Internet") {
          const mainServiceSkus = data.skus.filter(sku => {
            const upperSku = sku.toUpperCase();
            return (
              !upperSku.includes("INSTALL") &&
              !upperSku.includes("ADDON") &&
              !upperSku.includes("ACTIVATION") &&
              !upperSku.includes("FEE")
            );
          });
          return mainServiceSkus.length >= 1;
        }
        return true;
      },
      {
        message: "Internet orders must have at least one main service SKU (non-installation, non-addon)",
        path: ["skus"],
      }
    )
    .refine(
      (data) => {
        if (data.orderType === "SIM" && data.configurations) {
          return data.configurations.simType !== undefined;
        }
        return true;
      },
      {
        message: "SIM orders must specify SIM type",
        path: ["configurations", "simType"],
      }
    )
    .refine(
      (data) => {
        if (data.configurations?.simType === "eSIM") {
          return data.configurations.eid !== undefined && data.configurations.eid.length > 0;
        }
        return true;
      },
      {
        message: "eSIM orders must provide EID",
        path: ["configurations", "eid"],
      }
    )
    .refine(
      (data) => {
        if (data.configurations?.isMnp === "true") {
          const required = [
            "mnpNumber",
            "portingLastName",
            "portingFirstName",
          ] as const;
          return required.every(field => data.configurations?.[field] !== undefined);
        }
        return true;
      },
      {
        message: "MNP orders must provide porting information",
        path: ["configurations"],
      }
    );

export const sfOrderIdParamSchema = z.object({
  sfOrderId: z
    .string()
    .length(18, "Salesforce order ID must be 18 characters")
    .regex(/^[A-Za-z0-9]+$/, "Salesforce order ID must be alphanumeric"),
});

export type SfOrderIdParam = z.infer<typeof sfOrderIdParamSchema>;

// ============================================================================
// Checkout Schemas
// ============================================================================

/**
 * Schema for individual checkout items
 */
export const checkoutItemSchema = z.object({
  id: z.string(),
  sku: z.string(),
  name: z.string(),
  description: z.string().optional(),
  monthlyPrice: z.number().optional(),
  oneTimePrice: z.number().optional(),
  quantity: z.number().positive(),
  itemType: z.enum(['plan', 'installation', 'addon', 'activation', 'vpn']),
  autoAdded: z.boolean().optional(),
});

/**
 * Schema for checkout totals
 */
export const checkoutTotalsSchema = z.object({
  monthlyTotal: z.number(),
  oneTimeTotal: z.number(),
});

/**
 * Schema for complete checkout cart
 */
export const checkoutCartSchema = z.object({
  items: z.array(checkoutItemSchema),
  totals: checkoutTotalsSchema,
  configuration: orderConfigurationsSchema,
});

export const checkoutBuildCartRequestSchema = z.object({
  orderType: z.enum(["Internet", "SIM", "VPN", "Other"]),
  selections: orderSelectionsSchema,
  configuration: orderConfigurationsSchema.optional(),
});

export const checkoutBuildCartResponseSchema = apiSuccessResponseSchema(checkoutCartSchema);

/**
 * Schema for order creation response
 */
export const orderCreateResponseSchema = z.object({
  sfOrderId: z.string(),
  status: z.string(),
  message: z.string(),
});

// ============================================================================
// Inferred Types from Schemas (Schema-First Approach)
// ============================================================================

// Order item types
export type OrderItemSummary = z.infer<typeof orderItemSummarySchema>;
export type OrderItemDetails = z.infer<typeof orderItemDetailsSchema>;

// Order types
export type OrderSummary = z.infer<typeof orderSummarySchema>;
export type OrderDetails = z.infer<typeof orderDetailsSchema>;

// Query and creation types
export type OrderQueryParams = z.infer<typeof orderQueryParamsSchema>;
export type OrderConfigurationsAddress = z.infer<typeof orderConfigurationsAddressSchema>;
export type OrderConfigurations = z.infer<typeof orderConfigurationsSchema>;
export type CreateOrderRequest = z.infer<typeof createOrderRequestSchema>;
export type OrderBusinessValidation = z.infer<typeof orderBusinessValidationSchema>;
export type CheckoutBuildCartRequest = z.infer<typeof checkoutBuildCartRequestSchema>;
export type CheckoutBuildCartResponse = z.infer<typeof checkoutBuildCartResponseSchema>;

// ============================================================================
// Order Display Types (for UI presentation)
// ============================================================================

export const orderDisplayItemCategorySchema = z.enum([
  "service",
  "installation",
  "addon",
  "activation",
  "other",
]);

export const orderDisplayItemChargeKindSchema = z.enum([
  "monthly",
  "one-time",
  "other",
]);

export const orderDisplayItemChargeSchema = z.object({
  kind: orderDisplayItemChargeKindSchema,
  amount: z.number(),
  label: z.string(),
  suffix: z.string().optional(),
});

export const orderDisplayItemSchema = z.object({
  id: z.string(),
  name: z.string(),
  quantity: z.number().optional(),
  status: z.string().optional(),
  primaryCategory: orderDisplayItemCategorySchema,
  categories: z.array(orderDisplayItemCategorySchema),
  charges: z.array(orderDisplayItemChargeSchema),
  included: z.boolean(),
  sourceItems: z.array(orderItemSummarySchema),
  isBundle: z.boolean(),
});

// Types
export type OrderDisplayItemCategory = z.infer<typeof orderDisplayItemCategorySchema>;
export type OrderDisplayItemChargeKind = z.infer<typeof orderDisplayItemChargeKindSchema>;
export type OrderDisplayItemCharge = z.infer<typeof orderDisplayItemChargeSchema>;
export type OrderDisplayItem = z.infer<typeof orderDisplayItemSchema>;
