/**
 * Zod schemas for authentication API routes.
 *
 * These schemas are used at the API boundary to validate all inputs.
 * Import the schema to parse, and the inferred type for TypeScript.
 */

import { z } from 'zod';

// ---------------------------------------------------------------------------
// Turnstile token (Cloudflare bot/enumeration gate)
// ---------------------------------------------------------------------------

/**
 * Cloudflare Turnstile response token from the client widget. Required on the
 * credential/enumeration endpoints (login-email, register, magic-link/send).
 * Verified server-side via siteverify (see server/security/turnstile.ts).
 */
const turnstileTokenSchema = z.string().min(1).max(2048);

// ---------------------------------------------------------------------------
// Phone validation (Israeli mobile numbers)
// ---------------------------------------------------------------------------

/**
 * Israeli phone number: 10 digits starting with 05x, or E.164 format +972-5x-...
 * We normalize to E.164 before passing to Twilio.
 */
export const phoneSchema = z
  .string()
  .trim()
  .regex(/^\+?[0-9]{9,15}$/, 'Invalid phone number format');

export type Phone = z.infer<typeof phoneSchema>;

// ---------------------------------------------------------------------------
// Firebase Phone Auth schemas
// ---------------------------------------------------------------------------

export const firebaseVerifySchema = z.object({
  idToken: z.string().min(1, 'idToken required'),
});

export const firebaseVerifyBodySchema = z.object({
  idToken: z.string().min(1, 'idToken required'),
  // z.preprocess converts empty-string (cleared input) to undefined before email validation
  email: z.preprocess(
    (v) => (v === '' ? undefined : v),
    z
      .string()
      .trim()
      .check(z.email({ error: 'Invalid email address' }))
      .optional(),
  ),
  marketingConsent: z.boolean().optional().default(false),
});

export type FirebaseVerifyBody = z.infer<typeof firebaseVerifyBodySchema>;

// ---------------------------------------------------------------------------
// Magic link schemas
// ---------------------------------------------------------------------------

export const magicLinkBodySchema = z.object({
  token: z
    .string()
    .trim()
    .regex(/^[0-9a-f]{64}$/, 'Invalid magic link token'),
  /** Password is future-use in v1 - accepted but ignored. */
  password: z.string().optional(),
});

export type MagicLinkBody = z.infer<typeof magicLinkBodySchema>;

export const magicLinkSendBodySchema = z.object({
  email: z
    .string()
    .trim()
    .check(z.email({ error: 'Invalid email address' })),
  redirect: z.string().optional(),
  locale: z.enum(['he', 'en']).optional(),
  turnstileToken: turnstileTokenSchema,
});

export type MagicLinkSendBody = z.infer<typeof magicLinkSendBodySchema>;

// ---------------------------------------------------------------------------
// Email + password schemas
// ---------------------------------------------------------------------------

export const emailRegisterBodySchema = z.object({
  email: z
    .string()
    .trim()
    .check(z.email({ error: 'Invalid email address' })),
  password: z
    .string()
    .min(8, 'Password must be at least 8 characters')
    .regex(/[a-z]/, 'Password must contain at least one lowercase letter')
    .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')
    .regex(/[0-9]/, 'Password must contain at least one digit'),
  marketingConsent: z.boolean().optional().default(false),
  turnstileToken: turnstileTokenSchema,
});

export type EmailRegisterBody = z.infer<typeof emailRegisterBodySchema>;

export const emailLoginBodySchema = z.object({
  email: z
    .string()
    .trim()
    .check(z.email({ error: 'Invalid email address' })),
  password: z.string().min(1, 'Password required'),
  turnstileToken: turnstileTokenSchema,
});

export type EmailLoginBody = z.infer<typeof emailLoginBodySchema>;

// ---------------------------------------------------------------------------
// Session schemas
// ---------------------------------------------------------------------------

/** POST /api/auth/session - body is empty in v1, reserved for future use. */
export const sessionRefreshBodySchema = z.object({}).optional();

export type SessionRefreshBody = z.infer<typeof sessionRefreshBodySchema>;

/** POST /api/auth/logout - no body required. */
export const logoutBodySchema = z.object({}).optional();

export type LogoutBody = z.infer<typeof logoutBodySchema>;

// ---------------------------------------------------------------------------
// Shared response types
// ---------------------------------------------------------------------------

export interface ApiOkResponse {
  ok: true;
}

export interface ApiErrorResponse {
  ok: false;
  error: string;
  /** Machine-readable error code. */
  code?: string;
}

export type ApiResponse<T = Record<string, never>> = (ApiOkResponse & T) | ApiErrorResponse;

// ---------------------------------------------------------------------------
// User response shape (safe to return to client)
// ---------------------------------------------------------------------------

export interface PublicUser {
  id: string;
  displayName: string | null;
  isAdmin: boolean;
  accountState: string;
}
