/**
 * Zod validation schemas for Marketing & Leads Pipeline — marketing-leads-pipeline.
 * Shared between zync-api route handlers and zync-app React forms.
 * Re-exported through @zync/db/queries (no-raw-drizzle-from-routes policy).
 */
import { z } from 'zod'

// ── Enum schemas (must match schema CHECK constraints byte-for-byte) ──────────

export const leadStageSchema = z.enum([
  'NEW',
  'CONTACTED',
  'QUALIFIED',
  'PROPOSAL',
  'WON',
  'LOST',
])

export const leadSourceSchema = z.enum([
  'manual',
  'form',
  'webhook',
  'facebook',
  'google',
  'linkedin',
  'instagram',
  'zapier',
  'make',
  'referral',
  'cold_outreach',
])

export const leadActivityTypeSchema = z.enum([
  'note',
  'email_sent',
  'call_logged',
  'stage_changed',
  'form_submitted',
  'webhook_received',
  'converted',
  'contract_linked',
])

export const webhookSourceSchema = z.enum([
  'facebook',
  'google',
  'linkedin',
  'instagram',
  'zapier',
  'make',
  'generic',
])

// ── Field Config shape (lead_forms.fields JSONB) ──────────────────────────────

export const fieldConfigSchema = z.object({
  id: z.string().uuid(),
  type: z.enum(['text', 'email', 'phone', 'textarea', 'select', 'checkbox']),
  label: z.string().min(1).max(200),
  placeholder: z.string().max(200).optional(),
  required: z.boolean(),
  options: z.array(z.string().max(200)).optional(),
})

export type FieldConfig = z.infer<typeof fieldConfigSchema>

// ── Lead Form style shape ─────────────────────────────────────────────────────

export const formStyleSchema = z.object({
  primaryColor: z.string().max(20).optional(),
  logoR2Key: z.string().max(500).optional(),
  fontFamily: z.string().max(100).optional(),
})

export type FormStyle = z.infer<typeof formStyleSchema>

// ── Leads ────────────────────────────────────────────────────────────────────

export const createLeadSchema = z.object({
  name: z.string().min(1).max(500),
  email: z.string().email().max(320).nullable().optional(),
  phone: z.string().max(50).nullable().optional(),
  company: z.string().max(500).nullable().optional(),
  notes: z.string().max(10000).nullable().optional(),
  stage: leadStageSchema.optional().default('NEW'),
  source: leadSourceSchema.optional().default('manual'),
  assigned_to: z.string().uuid().nullable().optional(),
  estimated_value: z.string().regex(/^\d+(\.\d+)?$/).nullable().optional(),
  utm_source: z.string().max(200).nullable().optional(),
  utm_medium: z.string().max(200).nullable().optional(),
  utm_campaign: z.string().max(200).nullable().optional(),
  utm_content: z.string().max(200).nullable().optional(),
  utm_term: z.string().max(200).nullable().optional(),
})

export type CreateLeadInput = z.infer<typeof createLeadSchema>

export const updateLeadSchema = z.object({
  name: z.string().min(1).max(500).optional(),
  email: z.string().email().max(320).nullable().optional(),
  phone: z.string().max(50).nullable().optional(),
  company: z.string().max(500).nullable().optional(),
  notes: z.string().max(10000).nullable().optional(),
  stage: leadStageSchema.optional(),
  assigned_to: z.string().uuid().nullable().optional(),
  estimated_value: z.string().regex(/^\d+(\.\d+)?$/).nullable().optional(),
  lost_reason: z.string().max(1000).nullable().optional(),
  // lead-lost-re-engagement (wave-14): ISO datetime or null
  reengagement_at: z.string().datetime().nullable().optional(),
})

export type UpdateLeadInput = z.infer<typeof updateLeadSchema>

export const moveLeadSchema = z.object({
  stage: leadStageSchema,
  before_position: z.number().nullable().optional(),
  after_position: z.number().nullable().optional(),
})

export type MoveLeadInput = z.infer<typeof moveLeadSchema>

export const convertLeadSchema = z.object({
  customer_data: z.object({
    name: z.string().min(1).max(500),
    email: z.string().email().max(320).optional(),
    phone: z.string().max(50).nullable().optional(),
    company: z.string().max(500).nullable().optional(),
  }),
  project_data: z
    .object({
      name: z.string().min(1).max(500),
      description: z.string().max(5000).optional(),
    })
    .optional(),
})

export type ConvertLeadInput = z.infer<typeof convertLeadSchema>

export const leadFiltersSchema = z.object({
  stage: z.string().optional(),
  source: z.string().optional(),
  assigned_to: z.string().uuid().optional(),
  include_lost: z.coerce.boolean().optional().default(false),
  include_archived: z.coerce.boolean().optional().default(false),
  q: z.string().max(200).optional(),
  cursor: z.string().optional(),
  limit: z.coerce.number().int().min(1).max(100).optional().default(50),
  sort_by: z.enum(['name', 'stage', 'created_at', 'estimated_value', 'score']).optional().default('created_at'),
  sort_dir: z.enum(['asc', 'desc']).optional().default('desc'),
  // lead-qualification-scoring (wave-14)
  min_score: z.coerce.number().int().min(0).max(100).optional(),
})

export type LeadFiltersInput = z.infer<typeof leadFiltersSchema>

export const addLeadActivitySchema = z.object({
  type: leadActivityTypeSchema,
  content: z.string().max(10000).optional(),
  metadata: z.record(z.unknown()).optional(),
})

export type AddLeadActivityInput = z.infer<typeof addLeadActivitySchema>

// ── Lead Forms ────────────────────────────────────────────────────────────────

export const createLeadFormSchema = z.object({
  name: z.string().min(1).max(200),
  slug: z
    .string()
    .min(2)
    .max(100)
    .regex(/^[a-z0-9-]+$/, 'Slug must be lowercase alphanumeric with hyphens'),
  fields: z.array(fieldConfigSchema).min(1).max(30),
  redirect_url: z.string().url().max(2000).nullable().optional(),
  notify_email: z.string().email().max(320).nullable().optional(),
  style: formStyleSchema.optional(),
})

export type CreateLeadFormInput = z.infer<typeof createLeadFormSchema>

export const updateLeadFormSchema = z.object({
  name: z.string().min(1).max(200).optional(),
  // slug is immutable after first submission — enforced at route level
  slug: z
    .string()
    .min(2)
    .max(100)
    .regex(/^[a-z0-9-]+$/)
    .optional(),
  fields: z.array(fieldConfigSchema).min(1).max(30).optional(),
  redirect_url: z.string().url().max(2000).nullable().optional(),
  notify_email: z.string().email().max(320).nullable().optional(),
  style: formStyleSchema.optional(),
  is_active: z.boolean().optional(),
})

export type UpdateLeadFormInput = z.infer<typeof updateLeadFormSchema>

// ── Public Form Submission ────────────────────────────────────────────────────

export const publicFormSubmitSchema = z.object({
  // Keyed by field id (UUID string)
  payload: z.record(z.string().uuid(), z.unknown()),
  utm_source: z.string().max(200).optional(),
  utm_medium: z.string().max(200).optional(),
  utm_campaign: z.string().max(200).optional(),
  utm_content: z.string().max(200).optional(),
  utm_term: z.string().max(200).optional(),
})

export type PublicFormSubmitInput = z.infer<typeof publicFormSubmitSchema>

// ── Inbound Webhooks ──────────────────────────────────────────────────────────

export const createLeadWebhookSchema = z.object({
  name: z.string().min(1).max(200),
  source: webhookSourceSchema,
  secret: z.string().min(8).max(1000),
  field_mapping: z.record(z.string(), z.enum(['name', 'email', 'phone', 'company', 'notes'])).optional(),
})

export type CreateLeadWebhookInput = z.infer<typeof createLeadWebhookSchema>

export const updateLeadWebhookSchema = z.object({
  name: z.string().min(1).max(200).optional(),
  secret: z.string().min(8).max(1000).optional(),
  field_mapping: z
    .record(z.string(), z.enum(['name', 'email', 'phone', 'company', 'notes']))
    .optional(),
  is_active: z.boolean().optional(),
})

export type UpdateLeadWebhookInput = z.infer<typeof updateLeadWebhookSchema>

// ── Pipeline Stages ───────────────────────────────────────────────────────────

export const createPipelineStageSchema = z.object({
  name: z.string().min(1).max(100),
  slug: z
    .string()
    .min(1)
    .max(50)
    .regex(/^[A-Z0-9_]+$/, 'Stage slug must be uppercase alphanumeric with underscores'),
  color: z.string().max(20).optional(),
  position: z.number().positive(),
})

export type CreatePipelineStageInput = z.infer<typeof createPipelineStageSchema>

export const updatePipelineStageSchema = z.object({
  name: z.string().min(1).max(100).optional(),
  color: z.string().max(20).nullable().optional(),
  position: z.number().positive().optional(),
})

export type UpdatePipelineStageInput = z.infer<typeof updatePipelineStageSchema>
