/**
 * Subscriptions Domain - Schemas
 *
 * Zod validation schemas for subscription domain types.
 */

import { z } from "zod";

// Subscription Status Schema
export const subscriptionStatusSchema = z.enum([
  "Active",
  "Inactive",
  "Pending",
  "Cancelled",
  "Suspended",
  "Terminated",
  "Completed",
]);

// Subscription Cycle Schema
export const subscriptionCycleSchema = z.enum([
  "Monthly",
  "Quarterly",
  "Semi-Annually",
  "Annually",
  "Biennially",
  "Triennially",
  "One-time",
  "Free",
]);

// Subscription Schema
export const subscriptionSchema = z.object({
  id: z.number().int().positive("Subscription id must be positive"),
  serviceId: z.number().int().positive("Service id must be positive"),
  productName: z.string().min(1, "Product name is required"),
  domain: z.string().optional(),
  cycle: subscriptionCycleSchema,
  status: subscriptionStatusSchema,
  nextDue: z.string().optional(),
  amount: z.number(),
  currency: z.string().min(1, "Currency is required"),
  currencySymbol: z.string().optional(),
  registrationDate: z.string().min(1, "Registration date is required"),
  notes: z.string().optional(),
  customFields: z.record(z.string(), z.string()).optional(),
  orderNumber: z.string().optional(),
  groupName: z.string().optional(),
  paymentMethod: z.string().optional(),
  serverName: z.string().optional(),
});

export const subscriptionArraySchema = z.array(subscriptionSchema);

// Subscription List Schema
export const subscriptionListSchema = z.object({
  subscriptions: z.array(subscriptionSchema),
  totalCount: z.number().int().nonnegative(),
});

// ============================================================================
// Route Param Schemas (BFF)
// ============================================================================

export const subscriptionIdParamSchema = z.object({
  id: z.coerce.number().int().positive("Subscription id must be positive"),
});
export type SubscriptionIdParam = z.infer<typeof subscriptionIdParamSchema>;

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

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

export type SubscriptionQueryParams = z.infer<typeof subscriptionQueryParamsSchema>;

export const subscriptionQuerySchema = subscriptionQueryParamsSchema;
export type SubscriptionQuery = SubscriptionQueryParams;

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

/**
 * Schema for subscription statistics
 */
export const subscriptionStatsSchema = z.object({
  total: z.number().int().nonnegative(),
  active: z.number().int().nonnegative(),
  completed: z.number().int().nonnegative(),
  cancelled: z.number().int().nonnegative(),
});

/**
 * Schema for SIM action responses (top-up, cancellation, feature updates)
 */
export const simActionResponseSchema = z.object({
  message: z.string(),
  data: z.unknown().optional(),
});

/**
 * Schema for SIM plan change result with IP addresses
 */
export const simPlanChangeResultSchema = z.object({
  message: z.string(),
  ipv4: z.string().optional(),
  ipv6: z.string().optional(),
  scheduledAt: z
    .string()
    .regex(/^\d{8}$/, "Scheduled date must be in YYYYMMDD format")
    .optional(),
});

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

export type SubscriptionStatus = z.infer<typeof subscriptionStatusSchema>;
export type SubscriptionCycle = z.infer<typeof subscriptionCycleSchema>;
export type Subscription = z.infer<typeof subscriptionSchema>;
export type SubscriptionArray = z.infer<typeof subscriptionArraySchema>;
export type SubscriptionList = z.infer<typeof subscriptionListSchema>;
export type SubscriptionStats = z.infer<typeof subscriptionStatsSchema>;
export type SimActionResponse = z.infer<typeof simActionResponseSchema>;
export type SimPlanChangeResult = z.infer<typeof simPlanChangeResultSchema>;

// ============================================================================
// Internet Cancellation Schemas
// ============================================================================

/**
 * Available cancellation month for the customer
 */
export const internetCancellationMonthSchema = z.object({
  value: z.string(), // YYYY-MM format
  label: z.string(), // Display label like "November 2025"
});

/**
 * Internet cancellation preview response (service details + available months)
 */
export const internetCancellationPreviewSchema = z.object({
  productName: z.string(),
  billingAmount: z.number(),
  nextDueDate: z.string().optional(),
  registrationDate: z.string().optional(),
  availableMonths: z.array(internetCancellationMonthSchema),
  customerEmail: z.string(),
  customerName: z.string(),
});

/**
 * Internet cancellation request from customer
 */
export const internetCancelRequestSchema = z.object({
  cancellationMonth: z
    .string()
    .regex(/^\d{4}-\d{2}$/, "Cancellation month must be in YYYY-MM format"),
  confirmRead: z.boolean(),
  confirmCancel: z.boolean(),
  comments: z.string().max(1000).optional(),
});

export type InternetCancellationMonth = z.infer<typeof internetCancellationMonthSchema>;
export type InternetCancellationPreview = z.infer<typeof internetCancellationPreviewSchema>;
export type InternetCancelRequest = z.infer<typeof internetCancelRequestSchema>;

// ============================================================================
// Unified Cancellation Preview (SIM + Internet)
// ============================================================================

/**
 * Service type for cancellation flows
 */
export const serviceTypeSchema = z.enum(["sim", "internet"]);
export type ServiceType = z.infer<typeof serviceTypeSchema>;

/**
 * Structured notice/term content for cancellation pages
 */
export const cancellationNoticeSchema = z.object({
  title: z.string().min(1),
  content: z.string().min(1),
});
export type CancellationNotice = z.infer<typeof cancellationNoticeSchema>;

/**
 * Cancellation status derived from Salesforce Opportunity (if available)
 *
 * Notes:
 * - We only need a small subset for portal display.
 * - This is nullable because some services may not have a linked Opportunity.
 */
export const cancellationStatusSchema = z
  .object({
    stage: z.enum(["Active", "△Cancelling", "〇Cancelled"]),
    scheduledEndDate: z.string().optional(),
    // Internet only
    rentalReturnStatus: z.string().optional(),
  })
  .nullable();
export type CancellationStatus = z.infer<typeof cancellationStatusSchema>;

/**
 * Unified cancellation preview response used by the generic cancellation page.
 *
 * Includes:
 * - Service type + display fields
 * - Terms and notices (service-type specific)
 * - Cancellation status (derived from Opportunity when WHMCS isn't already cancelled)
 */
export const cancellationPreviewSchema = z.object({
  serviceType: serviceTypeSchema,
  serviceName: z.string().min(1),

  /**
   * Salesforce Opportunity ID read from WHMCS service custom fields (already stored in WHMCS).
   * Optional because not all services are guaranteed to have it.
   */
  opportunityId: z.string().min(15).max(18).optional(),

  serviceInfo: z.array(
    z.object({
      label: z.string().min(1),
      value: z.string().min(1),
      mono: z.boolean().optional(),
    })
  ),

  terms: z.array(cancellationNoticeSchema),
  warnings: z.array(cancellationNoticeSchema).default([]),
  step3Notices: z.array(cancellationNoticeSchema).default([]),

  cancellationStatus: cancellationStatusSchema,

  availableMonths: z.array(internetCancellationMonthSchema),
  customerEmail: z.string(),
  customerName: z.string().min(1),

  // SIM-specific (optional)
  isWithinMinimumTerm: z.boolean().optional(),
  minimumContractEndDate: z.string().optional(),
});

export type CancellationPreview = z.infer<typeof cancellationPreviewSchema>;
