/**
 * Auth Domain - Types
 * 
 * Contains ONLY authentication mechanism types:
 * - Login, Signup, Password Management
 * - Token Management
 * - MFA, SSO
 * 
 * User entity types are in customer domain.
 * Auth responses reference User from customer domain.
 */

import { z } from "zod";

import { emailSchema, nameSchema, passwordSchema, phoneSchema } from "../common/schema";
import { addressSchema, userSchema } from "../customer/schema";

// ============================================================================
// Authentication Request Schemas
// ============================================================================

const genderEnum = z.enum(["male", "female", "other"]);

export const loginRequestSchema = z.object({
  email: emailSchema,
  password: z.string().min(1, "Password is required"),
});

/**
 * Base signup input schema (before API transformation)
 * Used by frontend forms - can be extended with UI-specific fields (e.g., confirmPassword)
 */
export const signupInputSchema = z.object({
  email: emailSchema,
  password: passwordSchema,
  firstName: nameSchema,
  lastName: nameSchema,
  company: z.string().optional(),
  phone: phoneSchema,
  sfNumber: z.string().min(6, "Customer number must be at least 6 characters"),
  address: addressSchema.optional(),
  nationality: z.string().optional(),
  dateOfBirth: z.string().optional(),
  gender: genderEnum.optional(),
  acceptTerms: z.boolean(),
  marketingConsent: z.boolean().optional(),
});

/**
 * Signup request schema with API transformation
 * Transforms camelCase fields to match WHMCS API expectations
 */
export const signupRequestSchema = signupInputSchema.transform(data => ({
  ...data,
  firstname: data.firstName,
  lastname: data.lastName,
  companyname: data.company,
  phonenumber: data.phone,
}));

export const passwordResetRequestSchema = z.object({ email: emailSchema });

export const passwordResetSchema = z.object({
  token: z.string().min(1, "Reset token is required"),
  password: passwordSchema,
});

export const setPasswordRequestSchema = z.object({
  email: emailSchema,
  password: passwordSchema,
});

export const changePasswordRequestSchema = z.object({
  currentPassword: z.string().min(1, "Current password is required"),
  newPassword: passwordSchema,
});

export const linkWhmcsRequestSchema = z.object({
  email: emailSchema,
  password: z.string().min(1, "Password is required"),
});

export const validateSignupRequestSchema = z.object({
  sfNumber: z.string().min(1, "Customer number is required"),
});

/**
 * Schema for updating customer profile in WHMCS (single source of truth)
 * All fields optional - only send what needs to be updated
 * Can update profile fields and/or address fields in a single request
 */
export const updateCustomerProfileRequestSchema = z.object({
  // Basic profile
  firstname: nameSchema.optional(),
  lastname: nameSchema.optional(),
  companyname: z.string().max(100).optional(),
  phonenumber: phoneSchema.optional(),
  
  // Address (optional fields for partial updates)
  address1: z.string().max(200).optional(),
  address2: z.string().max(200).optional(),
  city: z.string().max(100).optional(),
  state: z.string().max(100).optional(),
  postcode: z.string().max(20).optional(),
  country: z.string().length(2).optional(), // ISO country code
  
  // Additional
  language: z.string().max(10).optional(),
});

export const updateProfileRequestSchema = updateCustomerProfileRequestSchema;
export const updateAddressRequestSchema = updateCustomerProfileRequestSchema;

export const accountStatusRequestSchema = z.object({
  email: emailSchema,
});

export const ssoLinkRequestSchema = z.object({
  destination: z.string().optional(),
});

export const checkPasswordNeededRequestSchema = z.object({
  email: emailSchema,
});

export const refreshTokenRequestSchema = z.object({
  refreshToken: z.string().min(1, "Refresh token is required").optional(),
  deviceId: z.string().optional(),
});

// ============================================================================
// Token Schemas
// ============================================================================

export const authTokensSchema = z.object({
  accessToken: z.string().min(1, "Access token is required"),
  refreshToken: z.string().min(1, "Refresh token is required"),
  expiresAt: z.string().min(1, "Access token expiry required"),
  refreshExpiresAt: z.string().min(1, "Refresh token expiry required"),
  tokenType: z.literal("Bearer"),
});

// ============================================================================
// Authentication Response Schemas (Reference User from Customer Domain)
// ============================================================================

/**
 * Auth response - returns User from customer domain
 */
export const authResponseSchema = z.object({
  user: userSchema,     // User from customer domain
  tokens: authTokensSchema,
});

/**
 * Signup result - returns User from customer domain
 */
export const signupResultSchema = z.object({
  user: userSchema,     // User from customer domain
  tokens: authTokensSchema,
});

/**
 * Password change result - returns User from customer domain
 */
export const passwordChangeResultSchema = z.object({
  user: userSchema,     // User from customer domain
  tokens: authTokensSchema,
});

/**
 * SSO link response
 */
export const ssoLinkResponseSchema = z.object({
  url: z.url(),
  expiresAt: z.string(),
});

/**
 * Check password needed response
 */
export const checkPasswordNeededResponseSchema = z.object({
  needsPasswordSet: z.boolean(),
  userExists: z.boolean(),
  email: z.email().optional(),
});

/**
 * Link WHMCS response
 */
export const linkWhmcsResponseSchema = z.object({
  user: userSchema,
  needsPasswordSet: z.boolean(),
});

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

// Request types
export type LoginRequest = z.infer<typeof loginRequestSchema>;
export type SignupRequest = z.infer<typeof signupRequestSchema>;
export type PasswordResetRequest = z.infer<typeof passwordResetRequestSchema>;
export type ResetPasswordRequest = z.infer<typeof passwordResetSchema>;
export type SetPasswordRequest = z.infer<typeof setPasswordRequestSchema>;
export type ChangePasswordRequest = z.infer<typeof changePasswordRequestSchema>;
export type LinkWhmcsRequest = z.infer<typeof linkWhmcsRequestSchema>;
export type ValidateSignupRequest = z.infer<typeof validateSignupRequestSchema>;
export type UpdateCustomerProfileRequest = z.infer<typeof updateCustomerProfileRequestSchema>;
export type AccountStatusRequest = z.infer<typeof accountStatusRequestSchema>;
export type SsoLinkRequest = z.infer<typeof ssoLinkRequestSchema>;
export type CheckPasswordNeededRequest = z.infer<typeof checkPasswordNeededRequestSchema>;
export type RefreshTokenRequest = z.infer<typeof refreshTokenRequestSchema>;

// Token types
export type AuthTokens = z.infer<typeof authTokensSchema>;

// Response types
export type AuthResponse = z.infer<typeof authResponseSchema>;
export type SignupResult = z.infer<typeof signupResultSchema>;
export type PasswordChangeResult = z.infer<typeof passwordChangeResultSchema>;
export type SsoLinkResponse = z.infer<typeof ssoLinkResponseSchema>;
export type CheckPasswordNeededResponse = z.infer<typeof checkPasswordNeededResponseSchema>;
export type LinkWhmcsResponse = z.infer<typeof linkWhmcsResponseSchema>;

// ============================================================================
// Error Types
// ============================================================================

export interface AuthError {
  code: "INVALID_CREDENTIALS" | "EMAIL_NOT_VERIFIED" | "ACCOUNT_LOCKED" | "MFA_REQUIRED" | "INVALID_TOKEN" | "TOKEN_EXPIRED" | "PASSWORD_TOO_WEAK" | "EMAIL_ALREADY_EXISTS" | "WHMCS_ACCOUNT_NOT_FOUND" | "SALESFORCE_ACCOUNT_NOT_FOUND" | "LINKING_FAILED";
  message: string;
  details?: unknown;
}

