/**
 * Get Started Domain - Schemas
 *
 * Zod validation schemas for the unified "Get Started" flow.
 */

import { z } from "zod";

import {
  emailSchema,
  nameSchema,
  passwordSchema,
  phoneSchema,
  genderEnum,
} from "../common/schema.js";
import { addressFormSchema } from "../customer/schema.js";

// ============================================================================
// Validation Message Constants
// ============================================================================

const SESSION_TOKEN_REQUIRED = "Session token is required";
const ACCEPT_TERMS_REQUIRED = "You must accept the terms of service";

// ============================================================================
// OTP Verification Schemas
// ============================================================================

/**
 * Request to send a verification code to an email address
 */
export const sendVerificationCodeRequestSchema = z.object({
  email: emailSchema,
});

/**
 * Response after sending verification code
 */
export const sendVerificationCodeResponseSchema = z.object({
  /** Whether the code was sent successfully */
  sent: z.boolean(),
  /** Message to display to user */
  message: z.string(),
  /** When a new code can be requested (ISO timestamp) */
  retryAfter: z.string().datetime().optional(),
});

/**
 * 6-digit OTP code schema
 */
export const otpCodeSchema = z
  .string()
  .length(6, "Code must be 6 digits")
  .regex(/^\d{6}$/, "Code must be 6 digits");

/**
 * Request to verify an OTP code
 */
export const verifyCodeRequestSchema = z.object({
  email: emailSchema,
  code: otpCodeSchema,
  /** Optional handoff token from guest eligibility check - used to pre-fill data */
  handoffToken: z.string().optional(),
});

/**
 * Account status enum for verification response
 */
export const accountStatusSchema = z.enum([
  "portal_exists",
  "whmcs_unmapped",
  "sf_unmapped",
  "new_customer",
]);

/**
 * Response after verifying OTP code
 * Includes account status to determine next flow
 */
export const verifyCodeResponseSchema = z.object({
  /** Whether the code was valid */
  verified: z.boolean(),
  /** Error message if verification failed */
  error: z.string().optional(),
  /** Remaining attempts if verification failed */
  attemptsRemaining: z.number().optional(),
  /** Session token for continuing the flow (only if verified) */
  sessionToken: z.string().optional(),
  /** Account status determining next flow (only if verified) */
  accountStatus: accountStatusSchema.optional(),
  /** Pre-filled data from existing account (only if SF or WHMCS exists) */
  prefill: z
    .object({
      firstName: z.string().optional(),
      lastName: z.string().optional(),
      email: z.string().optional(),
      phone: z.string().optional(),
      address: addressFormSchema.partial().optional(),
      eligibilityStatus: z.string().optional(),
    })
    .optional(),
});

// ============================================================================
// Helpers
// ============================================================================

/**
 * ISO date string (YYYY-MM-DD)
 */
const isoDateOnlySchema = z
  .string()
  .regex(/^\d{4}-\d{2}-\d{2}$/, "Enter a valid date (YYYY-MM-DD)")
  .refine(value => !Number.isNaN(Date.parse(value)), "Enter a valid date (YYYY-MM-DD)");

// ============================================================================
// Guest Eligibility Check Schemas (No OTP Required)
// ============================================================================

/**
 * Bilingual address schema for eligibility requests
 * Contains both English (for WHMCS) and Japanese (for Salesforce) address fields
 */
export const bilingualEligibilityAddressSchema = z.object({
  // English/Romanized fields (for WHMCS)
  address1: z.string().min(1, "Address is required").max(200).trim(),
  address2: z.string().max(200).trim().optional(),
  city: z.string().min(1, "City is required").max(100).trim(),
  state: z.string().min(1, "Prefecture is required").max(100).trim(),
  postcode: z.string().min(1, "Postcode is required").max(20).trim(),
  country: z.string().max(100).trim().optional(),

  // Japanese fields (for Salesforce)
  prefectureJa: z.string().max(100).trim().optional(),
  cityJa: z.string().max(100).trim().optional(),
  townJa: z.string().max(200).trim().optional(),
  streetAddress: z.string().max(50).trim().optional(),
  buildingName: z.string().max(200).trim().nullable().optional(),
  roomNumber: z.string().max(50).trim().nullable().optional(),
});

/**
 * Request for guest eligibility check - NO email verification required
 * Allows users to check availability without verifying email first
 */
export const guestEligibilityRequestSchema = z.object({
  /** Customer email (for notifications, not verified) */
  email: emailSchema,
  /** Customer first name */
  firstName: nameSchema,
  /** Customer last name */
  lastName: nameSchema,
  /** Full address with both English and Japanese fields for eligibility check */
  address: bilingualEligibilityAddressSchema,
  /** Optional phone number */
  phone: phoneSchema.optional(),
  /** Whether user wants to continue to account creation */
  continueToAccount: z.boolean().default(false),
});

/**
 * Response from guest eligibility check
 */
export const guestEligibilityResponseSchema = z.object({
  /** Whether the request was submitted successfully */
  submitted: z.boolean(),
  /** Case ID for the eligibility request */
  requestId: z.string().optional(),
  /** SF Account ID created */
  sfAccountId: z.string().optional(),
  /** Message to display */
  message: z.string(),
  /** Handoff token for account creation flow (if continueToAccount was true) */
  handoffToken: z.string().optional(),
});

/**
 * Guest handoff token data stored in Redis
 * Used to transfer data from eligibility check to account creation
 */
export const guestHandoffTokenSchema = z.object({
  /** Token ID */
  id: z.string(),
  /** Token type identifier */
  type: z.literal("guest_handoff"),
  /** Email address (NOT verified) */
  email: z.string(),
  /** Whether email has been verified (always false for guest handoff) */
  emailVerified: z.literal(false),
  /** First name */
  firstName: z.string(),
  /** Last name */
  lastName: z.string(),
  /** Address from eligibility check */
  address: addressFormSchema.partial().optional(),
  /** Phone number if provided */
  phone: z.string().optional(),
  /** SF Account ID created during eligibility check */
  sfAccountId: z.string(),
  /** Token creation timestamp */
  createdAt: z.string().datetime(),
});

// ============================================================================
// Account Completion Schemas
// ============================================================================

/**
 * Request to complete account for SF-only users or new customers
 * Creates WHMCS client and Portal user, links to existing SF Account (if any)
 *
 * For SF-only users: name/address comes from session (prefilled from handoff token)
 * For new customers: name/address must be provided in the request
 */
export const completeAccountRequestSchema = z.object({
  /** Session token from verified email */
  sessionToken: z.string().min(1, SESSION_TOKEN_REQUIRED),
  /** Customer first name (required for new customers, optional for SF-only) */
  firstName: nameSchema.optional(),
  /** Customer last name (required for new customers, optional for SF-only) */
  lastName: nameSchema.optional(),
  /** Address (required for new customers, optional for SF-only who have it in session) */
  address: addressFormSchema.optional(),
  /** Password for the new portal account */
  password: passwordSchema,
  /** Phone number (may be pre-filled from SF) */
  phone: phoneSchema,
  /** Date of birth */
  dateOfBirth: isoDateOnlySchema,
  /** Gender */
  gender: genderEnum,
  /** Accept terms of service */
  acceptTerms: z.boolean().refine(val => val === true, {
    message: ACCEPT_TERMS_REQUIRED,
  }),
  /** Marketing consent */
  marketingConsent: z.boolean().optional(),
});

// ============================================================================
// Signup With Eligibility Schema (Full Inline Signup)
// ============================================================================

/**
 * Request for full signup with eligibility check
 * Creates SF Account + Case + WHMCS + Portal in one operation
 * Used when user chooses "Create Account" on eligibility check page
 */
export const signupWithEligibilityRequestSchema = z.object({
  /** Session token from verified email */
  sessionToken: z.string().min(1, SESSION_TOKEN_REQUIRED),
  /** Customer first name */
  firstName: nameSchema,
  /** Customer last name */
  lastName: nameSchema,
  /** Full address for eligibility check and WHMCS */
  address: addressFormSchema,
  /** Phone number */
  phone: phoneSchema,
  /** Password for the new portal account */
  password: passwordSchema,
  /** Date of birth */
  dateOfBirth: isoDateOnlySchema,
  /** Gender */
  gender: genderEnum,
  /** Accept terms of service */
  acceptTerms: z.boolean().refine(val => val === true, {
    message: ACCEPT_TERMS_REQUIRED,
  }),
  /** Marketing consent */
  marketingConsent: z.boolean().optional(),
});

/**
 * Response from signup with eligibility
 */
export const signupWithEligibilityResponseSchema = z.object({
  /** Whether signup was successful */
  success: z.boolean(),
  /** Error message if failed */
  message: z.string().optional(),
  /** Case ID for the eligibility request (if successful) */
  eligibilityRequestId: z.string().optional(),
});

// ============================================================================
// WHMCS Migration Schema (Passwordless Migration)
// ============================================================================

/**
 * Request to migrate WHMCS account to portal without legacy password
 * For whmcs_unmapped users after email verification
 * Creates portal user and syncs password to WHMCS
 */
export const migrateWhmcsAccountRequestSchema = z.object({
  /** Session token from verified email */
  sessionToken: z.string().min(1, SESSION_TOKEN_REQUIRED),
  /** Password for the new portal account (will also sync to WHMCS) */
  password: passwordSchema,
  /** Date of birth */
  dateOfBirth: isoDateOnlySchema,
  /** Gender */
  gender: genderEnum,
  /** Accept terms of service */
  acceptTerms: z.boolean().refine(val => val === true, {
    message: ACCEPT_TERMS_REQUIRED,
  }),
  /** Marketing consent */
  marketingConsent: z.boolean().optional(),
});

// ============================================================================
// Session Schema
// ============================================================================

/**
 * Get Started session stored in Redis
 * Tracks progress through the unified flow
 */
export const getStartedSessionSchema = z.object({
  /** Email address (normalized) */
  email: z.string(),
  /** Whether email has been verified via OTP */
  emailVerified: z.boolean(),
  /** First name (if provided during quick check) */
  firstName: z.string().optional(),
  /** Last name (if provided during quick check) */
  lastName: z.string().optional(),
  /** Address (if provided during quick check) */
  address: addressFormSchema.partial().optional(),
  /** Phone number (if provided) */
  phone: z.string().optional(),
  /** Account status after verification */
  accountStatus: accountStatusSchema.optional(),
  /** SF Account ID (if exists or created) */
  sfAccountId: z.string().optional(),
  /** WHMCS Client ID (if exists) */
  whmcsClientId: z.number().optional(),
  /** Eligibility status from SF */
  eligibilityStatus: z.string().optional(),
  /** Session creation timestamp */
  createdAt: z.string().datetime(),
  /** Session expiry timestamp */
  expiresAt: z.string().datetime(),
});
