import { AbilityScoresSchema } from '@dng/shared' import { z } from 'zod' import { requireCampaignAccess, requireStageTwoSafeText, requireStageTwoUser, stageTwoApiError, stageTwoDatabase, stageTwoRpc, stageTwoUuid } from '~/server/utils/stage-two-supabase' const BodySchema = z.object({ name: z.string().trim().min(1).max(80), concept: z.string().trim().min(3).max(600), controller: z.enum(['human', 'ai']).default('human'), abilities: AbilityScoresSchema, hp: z.number().int().min(0), maxHp: z.number().int().min(1), defense: z.number().int().min(1).max(40), proficiency: z.number().int().min(1).max(10).default(2), inventory: z.array(z.string().trim().min(1).max(120)).max(50).default([]), statuses: z.array(z.string().trim().min(1).max(80)).max(12).default([]), persona: z.record(z.string(), z.unknown()).default({}), }).strict().refine(value => value.hp <= value.maxHp, { message: 'hp must not exceed maxHp', path: ['hp'] }) export default defineEventHandler(async (event) => { try { const user = await requireStageTwoUser(event) const campaignId = stageTwoUuid(getRouterParam(event, 'id'), 'campaign id') const access = await requireCampaignAccess(campaignId, user.id) const body = BodySchema.parse(await readBody(event)) if (body.controller === 'ai' && !access.owner) { throw createError({ statusCode: 403, statusMessage: 'Only the campaign owner can add AI heroes.' }) } requireStageTwoSafeText([body.name, body.concept, ...body.inventory, ...body.statuses, JSON.stringify(body.persona)].join('\n')) const characterId = await stageTwoRpc('stage_four_create_character', { p_campaign_id: campaignId, p_actor_id: user.id, p_controller: body.controller, p_name: body.name, p_concept: body.concept, p_abilities: body.abilities, p_hp: body.hp, p_max_hp: body.maxHp, p_defense: body.defense, p_proficiency: body.proficiency, p_inventory: body.inventory, p_statuses: body.statuses, p_persona: body.persona, }) const rows = await stageTwoDatabase>>( `characters?select=*&id=eq.${characterId}&campaign_id=eq.${campaignId}&limit=1`, ) setResponseStatus(event, 201) return { character: rows[0] } } catch (error) { stageTwoApiError(error) } })