/**
 * SIM Domain - Freebit Provider Request Schemas
 * 
 * Zod schemas for all Freebit API request payloads.
 */

import { z } from "zod";

// ============================================================================
// Account Details & Traffic Info
// ============================================================================

export const freebitAccountDetailsRequestSchema = z.object({
  version: z.string().optional(),
  requestDatas: z
    .array(
      z.object({
        kind: z.enum(["MASTER", "MVNO"]),
        account: z.union([z.string(), z.number()]).optional(),
      })
    )
    .min(1, "At least one request data entry is required"),
});

export const freebitTrafficInfoRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
});

// ============================================================================
// Top-Up
// ============================================================================

export const freebitTopUpOptionsSchema = z.object({
  campaignCode: z.string().optional(),
  expiryDate: z.string().optional(),
  scheduledAt: z.string().optional(),
});

export const freebitTopUpRequestPayloadSchema = z.object({
  account: z.string().min(1, "Account is required"),
  quotaMb: z.number().positive("Quota must be positive"),
  options: freebitTopUpOptionsSchema.optional(),
});

export const freebitTopUpApiRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  quota: z.number().positive("Quota must be positive"),
  quotaCode: z.string().optional(),
  expire: z.string().optional(),
  runTime: z.string().optional(),
});

// ============================================================================
// Plan Change & Cancellation
// ============================================================================

export const freebitPlanChangeRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  newPlanCode: z.string().min(1, "New plan code is required"),
  assignGlobalIp: z.boolean().optional(),
  scheduledAt: z.string().optional(),
});

export const freebitPlanChangeApiRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  plancode: z.string().min(1, "Plan code is required"),
  globalip: z.enum(["0", "1"]).optional(),
  runTime: z.string().optional(),
});

export const freebitAddSpecRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  specCode: z.string().min(1, "Spec code is required"),
  enabled: z.boolean().optional(),
  networkType: z.enum(["4G", "5G"]).optional(),
});

export const freebitRemoveSpecRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  specCode: z.string().min(1, "Spec code is required"),
});

export const freebitCancelPlanRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  runDate: z.string().optional(),
});

export const freebitCancelPlanApiRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  runTime: z.string().optional(),
});

export const freebitQuotaHistoryRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  fromDate: z.string().regex(/^\d{8}$/, "From date must be in YYYYMMDD format"),
  toDate: z.string().regex(/^\d{8}$/, "To date must be in YYYYMMDD format"),
});

export const freebitQuotaHistoryResponseSchema = z.object({
  resultCode: z.string(),
  status: z
    .object({
      message: z.string(),
      statusCode: z.union([z.string(), z.number()]),
    })
    .optional(),
  total: z.union([z.string(), z.number()]),
  count: z.union([z.string(), z.number()]),
  quotaHistory: z.array(
    z.object({
      addQuotaKb: z.union([z.string(), z.number()]),
      addDate: z.string(),
      expireDate: z.string(),
      campaignCode: z.string().optional(),
    })
  ),
});

export const freebitEsimMnpSchema = z.object({
  reserveNumber: z.string().min(1, "Reserve number is required"),
  reserveExpireDate: z.string().regex(/^\d{8}$/, "Reserve expire date must be in YYYYMMDD format"),
});

export const freebitEsimReissueRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  newEid: z.string().min(1, "New EID is required"),
  oldEid: z.string().optional(),
  planCode: z.string().optional(),
  oldProductNumber: z.string().optional(),
});

export const freebitEsimAddAccountRequestSchema = z.object({
  authKey: z.string().min(1).optional(),
  aladinOperated: z.enum(["10", "20"]).default("10"),
  account: z.string().min(1, "Account is required"),
  eid: z.string().min(1, "EID is required"),
  addKind: z.enum(["N", "R"]).default("N"),
  shipDate: z.string().regex(/^\d{8}$/, "Ship date must be in YYYYMMDD format").optional(),
  planCode: z.string().optional(),
  contractLine: z.enum(["4G", "5G"]).optional(),
  mnp: freebitEsimMnpSchema.optional(),
});

// =========================================================================
// SIM Features
// =========================================================================

export const freebitSimFeaturesRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  voiceMailEnabled: z.boolean().optional(),
  callWaitingEnabled: z.boolean().optional(),
  callForwardingEnabled: z.boolean().optional(),
  callerIdEnabled: z.boolean().optional(),
});

export const freebitGlobalIpRequestSchema = z.object({
  account: z.string().min(1, "Account is required"),
  assign: z.boolean(), // true to assign, false to remove
});

// =========================================================================
// eSIM Activation
// =========================================================================

export const freebitAuthRequestSchema = z.object({
  oemId: z.string().min(1),
  oemKey: z.string().min(1),
});

export const freebitCancelAccountRequestSchema = z.object({
  account: z.string().min(1),
  runDate: z.string().optional(),
});

export const freebitEsimIdentitySchema = z.object({
  firstnameKanji: z.string().optional(),
  lastnameKanji: z.string().optional(),
  firstnameZenKana: z.string().optional(),
  lastnameZenKana: z.string().optional(),
  gender: z.enum(["M", "F"]).optional(),
  birthday: z.string().regex(/^\d{8}$/, "Birthday must be in YYYYMMDD format").optional(),
});

/**
 * Freebit eSIM Account Activation Request Schema
 * PA05-41 (addAcct) API endpoint
 */
export const freebitEsimActivationRequestSchema = z.object({
  authKey: z.string().min(1, "Auth key is required"),
  aladinOperated: z.enum(["10", "20"]).default("10"), // 10: issue profile, 20: no-issue
  createType: z.enum(["new", "reissue", "exchange"]).default("new"),
  account: z.string().min(1, "Account (MSISDN) is required"),
  eid: z.string().min(1, "EID is required for eSIM"),
  simkind: z.enum(["esim", "psim"]).default("esim"),
  planCode: z.string().optional(),
  contractLine: z.enum(["4G", "5G"]).optional(),
  shipDate: z.string().regex(/^\d{8}$/, "Ship date must be in YYYYMMDD format").optional(),
  mnp: freebitEsimMnpSchema.optional(),
  // Identity fields (flattened for API)
  firstnameKanji: z.string().optional(),
  lastnameKanji: z.string().optional(),
  firstnameZenKana: z.string().optional(),
  lastnameZenKana: z.string().optional(),
  gender: z.enum(["M", "F"]).optional(),
  birthday: z.string().regex(/^\d{8}$/, "Birthday must be in YYYYMMDD format").optional(),
  // Additional fields for reissue/exchange
  masterAccount: z.string().optional(),
  masterPassword: z.string().optional(),
  repAccount: z.string().optional(),
  size: z.string().optional(),
  addKind: z.string().optional(), // 'R' for reissue
  oldEid: z.string().optional(),
  oldProductNumber: z.string().optional(),
  deliveryCode: z.string().optional(),
  globalIp: z.enum(["10", "20"]).optional(), // 10: none, 20: with global IP
});

/**
 * Freebit eSIM Activation Response Schema
 * Note: The 'data' field type varies by API version and is not used in production.
 * Using z.unknown() for type safety while allowing any shape if present.
 */
export const freebitEsimActivationResponseSchema = z.object({
  resultCode: z.string(),
  resultMessage: z.string().optional(),
  data: z.unknown().optional(),
  status: z.object({
    statusCode: z.union([z.string(), z.number()]),
    message: z.string(),
  }).optional(),
  message: z.string().optional(),
});

/**
 * Higher-level eSIM activation parameters schema
 * Used for business logic layer before mapping to API request
 */
export const freebitEsimActivationParamsSchema = z.object({
  account: z.string().min(1, "Account is required"),
  eid: z.string().min(1, "EID is required"),
  planCode: z.string().optional(),
  contractLine: z.enum(["4G", "5G"]).optional(),
  aladinOperated: z.enum(["10", "20"]).default("10"),
  shipDate: z.string().regex(/^\d{8}$/, "Ship date must be in YYYYMMDD format").optional(),
  mnp: freebitEsimMnpSchema.optional(),
  identity: freebitEsimIdentitySchema.optional(),
});

// ============================================================================
// Type Exports
// ============================================================================

export type FreebitAccountDetailsRequest = z.infer<typeof freebitAccountDetailsRequestSchema>;
export type FreebitTrafficInfoRequest = z.infer<typeof freebitTrafficInfoRequestSchema>;
export type FreebitTopUpRequest = z.infer<typeof freebitTopUpRequestPayloadSchema>;
export type FreebitTopUpApiRequest = z.infer<typeof freebitTopUpApiRequestSchema>;
export type FreebitPlanChangeRequest = z.infer<typeof freebitPlanChangeRequestSchema>;
export type FreebitPlanChangeApiRequest = z.infer<typeof freebitPlanChangeApiRequestSchema>;
export type FreebitAddSpecRequest = z.infer<typeof freebitAddSpecRequestSchema>;
export type FreebitRemoveSpecRequest = z.infer<typeof freebitRemoveSpecRequestSchema>;
export type FreebitCancelPlanRequest = z.infer<typeof freebitCancelPlanRequestSchema>;
export type FreebitCancelPlanApiRequest = z.infer<typeof freebitCancelPlanApiRequestSchema>;
export type FreebitSimFeaturesRequest = z.infer<typeof freebitSimFeaturesRequestSchema>;
export type FreebitGlobalIpRequest = z.infer<typeof freebitGlobalIpRequestSchema>;
export type FreebitEsimActivationRequest = z.infer<typeof freebitEsimActivationRequestSchema>;
export type FreebitEsimActivationResponse = z.infer<typeof freebitEsimActivationResponseSchema>;
export type FreebitEsimActivationParams = z.infer<typeof freebitEsimActivationParamsSchema>;
export type FreebitEsimReissueRequest = z.infer<typeof freebitEsimReissueRequestSchema>;
export type FreebitQuotaHistoryRequest = z.infer<typeof freebitQuotaHistoryRequestSchema>;
export type FreebitQuotaHistoryResponse = z.infer<typeof freebitQuotaHistoryResponseSchema>;
export type FreebitEsimAddAccountRequest = z.infer<typeof freebitEsimAddAccountRequestSchema>;
export type FreebitAuthRequest = z.infer<typeof freebitAuthRequestSchema>;
export type FreebitCancelAccountRequest = z.infer<typeof freebitCancelAccountRequestSchema>;

