import * as z from 'zod'
import { ADMIN_ALERT_TYPES } from '../models/adminAlertDismissal.js'

export const emailSchema = z.object({
  email: z.string().trim().toLowerCase().email()
})

export const memberCreateSchema = z.object({
  email: z.string().trim().toLowerCase().email(),
  name: z.string().min(1).max(200),
  circle: z.enum(['community', 'founder', 'practitioner']),
  contributionAmount: z.number().int().min(0)
})

export const memberProfileUpdateSchema = z.object({
  pronouns: z.string().max(100).optional(),
  timeZone: z.string().max(100).optional(),
  avatar: z.string().max(500).optional(),
  studio: z.string().max(200).optional(),
  bio: z.string().max(5000).optional(),
  location: z.string().max(200).optional(),
  socialLinks: z.object({
    mastodon: z.string().max(300).optional(),
    linkedin: z.string().max(300).optional(),
    website: z.string().max(300).optional(),
    other: z.string().max(300).optional()
  }).optional(),
  showInDirectory: z.boolean().optional(),
  notifications: z.object({
    events: z.boolean().optional()
  }).optional(),
  craftTags: z.array(z.string().max(100)).max(16).optional(),
  boardSlackHandle: z.string().max(200).optional()
})

export const eventRegistrationSchema = z.object({
  name: z.string().min(1).max(200),
  email: z.string().trim().toLowerCase().email(),
  dietary: z.boolean().optional()
})

export const paymentVerifySchema = z.object({
  cardToken: z.string().min(1),
  customerId: z.union([z.string(), z.number()]).transform(String)
})

// --- Helcim schemas ---

export const helcimCreatePlanSchema = z.object({
  name: z.string().min(1).max(200),
  amount: z.union([z.string().min(1), z.number().positive()]),
  frequency: z.string().min(1).max(50),
  currency: z.string().max(10).optional()
})

export const helcimCustomerSchema = z.object({
  name: z.string().min(1).max(200),
  email: z.string().trim().toLowerCase().email(),
  circle: z.enum(['community', 'founder', 'practitioner']).optional(),
  contributionAmount: z.number().int().min(0).optional(),
  agreedToGuidelines: z.literal(true)
})

export const helcimInitializePaymentSchema = z.object({
  amount: z.number().min(0).optional(),
  customerCode: z.string().max(200).optional(),
  metadata: z.object({
    type: z.string().max(100).optional(),
    eventTitle: z.string().max(500).optional(),
    eventId: z.string().max(200).optional()
  }).optional()
})

export const helcimSubscriptionSchema = z.object({
  customerId: z.union([z.string().min(1), z.number()]),
  contributionAmount: z.number().int().min(0),
  customerCode: z.union([z.string().min(1).max(200), z.number()]).transform(String),
  cardToken: z.string().max(500).optional().nullable(),
  cadence: z.enum(['monthly', 'annual']).default('monthly')
})

export const helcimUpdateCardSchema = z.object({
  cardToken: z.string().min(1).max(500)
})

export const helcimUpdateBillingSchema = z.object({
  customerId: z.union([z.string().min(1), z.number()]),
  billingAddress: z.object({
    name: z.string().max(200).optional(),
    street: z.string().min(1).max(500),
    city: z.string().min(1).max(200),
    province: z.string().max(200).optional(),
    state: z.string().max(200).optional(),
    country: z.string().min(1).max(100),
    postalCode: z.string().min(1).max(20)
  })
})

// --- Event ticket/registration schemas ---

export const ticketPurchaseSchema = z.object({
  name: z.string().min(1).max(200),
  email: z.string().trim().toLowerCase().email(),
  transactionId: z.string().max(500).optional(),
  createAccount: z.boolean().optional().default(true)
})

export const ticketReserveSchema = z.object({
  email: z.string().trim().toLowerCase().email()
})

export const ticketEligibilitySchema = z.object({
  email: z.string().trim().toLowerCase().email()
})

export const waitlistSchema = z.object({
  name: z.string().max(200).optional(),
  email: z.string().trim().toLowerCase().email(),
  membershipLevel: z.string().max(100).optional()
})

export const waitlistDeleteSchema = z.object({
  email: z.string().trim().toLowerCase().email()
})

export const cancelRegistrationSchema = z.object({
  email: z.string().trim().toLowerCase().email()
})

export const checkRegistrationSchema = z.object({
  email: z.string().trim().toLowerCase().email()
})

export const eventPaymentSchema = z.object({
  name: z.string().min(1).max(200),
  email: z.string().trim().toLowerCase().email(),
  paymentToken: z.string().min(1).max(500)
})

// --- Member schemas ---

export const updateContributionSchema = z.object({
  contributionAmount: z.number().int().min(0),
  cadence: z.enum(['monthly', 'annual']).default('monthly')
})

export const updateCircleSchema = z.object({
  circle: z.enum(['community', 'founder', 'practitioner'])
})

// --- Series ticket schemas ---

export const seriesTicketPurchaseSchema = z.object({
  name: z.string().min(1).max(200),
  email: z.string().trim().toLowerCase().email(),
  paymentId: z.string().max(500).optional(),
  ticketType: z.enum(['member', 'public', 'guest']),
})

export const seriesTicketEligibilitySchema = z.object({
  email: z.string().trim().toLowerCase().email()
})

// --- Admin schemas ---

const emptyStringToUndefined = (v) => (v === '' ? undefined : v)

export const adminEventCreateSchema = z.object({
  title: z.string().min(1).max(500),
  description: z.string().min(1).max(50000),
  startDate: z.string().min(1),
  endDate: z.string().min(1),
  location: z.string().max(500).optional(),
  maxAttendees: z.preprocess(emptyStringToUndefined, z.number().int().positive().optional().nullable()),
  membersOnly: z.boolean().optional(),
  registrationDeadline: z.preprocess(emptyStringToUndefined, z.string().optional().nullable()),
  pricing: z.object({
    paymentRequired: z.boolean().optional(),
    isFree: z.boolean().optional()
  }).optional(),
  tickets: z.object({
    enabled: z.boolean().optional(),
    public: z.object({
      available: z.boolean().optional(),
      name: z.string().max(200).optional(),
      description: z.string().max(2000).optional(),
      price: z.number().min(0).optional(),
      quantity: z.preprocess(emptyStringToUndefined, z.number().int().positive().optional().nullable()),
      earlyBirdPrice: z.preprocess(emptyStringToUndefined, z.number().min(0).optional().nullable()),
      earlyBirdDeadline: z.preprocess(emptyStringToUndefined, z.string().optional().nullable())
    }).optional()
  }).optional(),
  image: z.string().url().optional().nullable(),
  category: z.string().max(100).optional(),
  tags: z.array(z.string().max(100)).max(20).optional(),
  series: z.any().optional()
}).passthrough()

export const adminEventUpdateSchema = z.object({
  title: z.string().min(1).max(500),
  description: z.string().min(1).max(50000),
  startDate: z.string().min(1),
  endDate: z.string().min(1),
  location: z.string().max(500).optional(),
  maxAttendees: z.preprocess(emptyStringToUndefined, z.number().int().positive().optional().nullable()),
  membersOnly: z.boolean().optional(),
  registrationDeadline: z.preprocess(emptyStringToUndefined, z.string().optional().nullable()),
  pricing: z.object({
    paymentRequired: z.boolean().optional(),
    isFree: z.boolean().optional(),
    publicPrice: z.number().min(0).optional()
  }).optional(),
  tickets: z.object({
    enabled: z.boolean().optional(),
    public: z.object({
      available: z.boolean().optional(),
      name: z.string().max(200).optional(),
      description: z.string().max(2000).optional(),
      price: z.number().min(0).optional(),
      quantity: z.preprocess(emptyStringToUndefined, z.number().int().positive().optional().nullable()),
      sold: z.number().int().min(0).optional(),
      earlyBirdPrice: z.preprocess(emptyStringToUndefined, z.number().min(0).optional().nullable()),
      earlyBirdDeadline: z.preprocess(emptyStringToUndefined, z.string().optional().nullable())
    }).optional()
  }).optional(),
  image: z.string().url().optional().nullable(),
  category: z.string().max(100).optional(),
  tags: z.array(z.string().max(100)).max(20).optional(),
  series: z.any().optional(),
  slug: z.string().max(500).optional()
}).passthrough()

export const adminSeriesCreateSchema = z.object({
  id: z.string().min(1).max(200),
  title: z.string().min(1).max(500),
  description: z.string().min(1).max(50000),
  type: z.string().max(100).optional(),
  totalEvents: z.number().int().positive().optional().nullable()
})

export const adminSeriesUpdateSchema = z.object({
  id: z.string().min(1).max(200),
  title: z.string().min(1).max(500),
  description: z.string().max(50000).optional(),
  type: z.string().max(100).optional(),
  totalEvents: z.number().int().positive().optional().nullable()
})

export const adminSeriesItemUpdateSchema = z.object({
  title: z.string().min(1).max(500).optional(),
  description: z.string().max(50000).optional(),
  type: z.string().max(100).optional(),
  totalEvents: z.number().int().positive().optional().nullable(),
  isActive: z.boolean().optional()
})

export const adminSeriesTicketsSchema = z.object({
  id: z.string().min(1).max(200),
  tickets: z.object({
    enabled: z.boolean().optional(),
    requiresSeriesTicket: z.boolean().optional(),
    allowIndividualEventTickets: z.boolean().optional(),
    currency: z.string().max(10).optional(),
    member: z.object({
      available: z.boolean().optional(),
      isFree: z.boolean().optional(),
      price: z.number().min(0).optional(),
      name: z.string().max(200).optional(),
      description: z.string().max(2000).optional(),
      circleOverrides: z.record(z.any()).optional()
    }).optional(),
    public: z.object({
      available: z.boolean().optional(),
      name: z.string().max(200).optional(),
      description: z.string().max(2000).optional(),
      price: z.number().min(0).optional(),
      quantity: z.number().int().positive().optional().nullable(),
      sold: z.number().int().min(0).optional(),
      reserved: z.number().int().min(0).optional(),
      earlyBirdPrice: z.number().min(0).optional().nullable(),
      earlyBirdDeadline: z.string().optional().nullable()
    }).optional(),
    capacity: z.object({
      total: z.number().int().positive().optional().nullable(),
      reserved: z.number().int().min(0).optional()
    }).optional(),
    waitlist: z.object({
      enabled: z.boolean().optional(),
      maxSize: z.number().int().positive().optional().nullable(),
      entries: z.array(z.any()).optional()
    }).optional()
  })
})

export const adminMemberCreateSchema = z.object({
  name: z.string().min(1).max(200),
  email: z.string().trim().toLowerCase().email(),
  circle: z.enum(['community', 'founder', 'practitioner']),
  contributionAmount: z.number().int().min(0)
})

export const adminMemberUpdateSchema = z.object({
  name: z.string().min(1).max(200),
  email: z.string().trim().toLowerCase().email(),
  circle: z.enum(['community', 'founder', 'practitioner']),
  contributionAmount: z.number().int().min(0),
  status: z.enum(['pending_payment', 'active', 'suspended', 'cancelled'])
})

export const adminRoleUpdateSchema = z.object({
  role: z.enum(['admin', 'member'])
})

export const bulkMemberImportSchema = z.object({
  members: z.array(z.object({
    name: z.string().min(1).max(200),
    email: z.string().trim().toLowerCase().email(),
    circle: z.enum(['community', 'founder', 'practitioner']),
    contributionAmount: z.number().int().min(0)
  })).min(1).max(100)
})

export const memberInviteSchema = z.object({
  memberIds: z.array(z.string().min(1)).min(1).max(100),
  emailTemplate: z.string().min(1).max(10000)
})

// --- Pre-registrant schemas ---

export const preRegistrantStatusUpdateSchema = z.object({
  status: z.enum(['pending', 'selected']),
  adminNotes: z.string().max(2000).optional()
})

export const preRegistrantBulkStatusSchema = z.object({
  ids: z.array(z.string().min(1)).min(1).max(100),
  status: z.enum(['pending', 'selected'])
})

export const preRegistrantInviteSchema = z.object({
  preRegistrantIds: z.array(z.string().min(1)).min(1).max(20),
  emailTemplate: z.string().min(1).max(10000)
})

export const inviteVerifySchema = z.object({
  token: z.string().min(1)
})

export const inviteAcceptSchema = z.object({
  preRegistrationId: z.string().min(1),
  name: z.string().min(1).max(200),
  pronouns: z.string().max(100).optional(),
  location: z.string().max(200).optional(),
  circle: z.enum(['community', 'founder', 'practitioner']),
  motivation: z.string().max(5000).optional(),
  contributionAmount: z.number().int().min(0),
  agreedToGuidelines: z.literal(true),
  token: z.string().min(1)
})

// --- Onboarding schemas ---

export const onboardingTrackSchema = z.object({
  goal: z.enum(['eventPageVisited', 'boardPageVisited', 'wikiClicked']).optional(),
  skip: z.enum(['profileTags', 'visitEvent', 'board', 'wiki']).optional(),
}).refine((v) => v.goal || v.skip, {
  message: 'Must provide goal or skip',
})

// --- Tag schemas ---

export const tagSuggestionSchema = z.object({
  label: z.string().min(1).max(100),
  pool: z.enum(['craft', 'cooperative'])
})

// --- Board post / channel schemas ---

export const boardPostCreateSchema = z.object({
  title: z.string().trim().min(1).max(120),
  seeking: z.string().max(500).optional(),
  offering: z.string().max(500).optional(),
  note: z.string().max(300).optional(),
  tags: z.array(z.string().max(100)).optional().default([])
}).refine(
  (data) => (data.seeking || '').trim().length > 0 || (data.offering || '').trim().length > 0,
  { message: 'At least one of seeking or offering must be provided', path: ['seeking'] }
)

export const boardPostUpdateSchema = z.object({
  title: z.string().trim().min(1).max(120).optional(),
  seeking: z.string().max(500).optional(),
  offering: z.string().max(500).optional(),
  note: z.string().max(300).optional(),
  tags: z.array(z.string().max(100)).optional()
})

export const boardChannelCreateSchema = z.object({
  name: z.string().trim().min(1).max(200),
  slackChannelId: z.string().trim().min(1).max(50).regex(/^[A-Z0-9]+$/, 'Invalid Slack channel ID').optional(),
  tagSlugs: z.array(z.string().max(100)).optional().default([])
})

export const boardChannelUpdateSchema = z.object({
  name: z.string().trim().min(1).max(200).optional(),
  slackChannelId: z.string().trim().min(1).max(50).regex(/^[A-Z0-9]+$/, 'Invalid Slack channel ID').optional(),
  tagSlugs: z.array(z.string().max(100)).optional()
})

// --- Admin alert schemas ---

export const adminAlertDismissSchema = z.object({
  alertType: z.enum(ADMIN_ALERT_TYPES),
  signature: z.string().min(1).max(128)
})

export const adminAlertRestoreSchema = z.object({
  alertTypes: z
    .array(z.enum(ADMIN_ALERT_TYPES))
    .min(1)
    .max(ADMIN_ALERT_TYPES.length)
})

// --- Site content (key/value editable copy blocks) ---

export const SITE_CONTENT_KEYS = ['homepage.wiki_feature']

export const siteContentUpsertSchema = z.object({
  title: z.string().max(300).optional(),
  body: z.string().max(5000).optional()
})
