import { v4 as uuid } from 'uuid'; import db from '../db/connection.js'; import type { CreateShipInput, UpdateShipInput } from '../validation/ship-schema.js'; export interface Ship { id: string; name: string; hull_current: number; hull_max: number; armor_current: number; armor_max: number; ac: number; con_save: number | null; speed: number | null; maneuver_class: string | null; size_category: string | null; notes: string | null; updated_at: number; } export interface Weapon { id: string; ship_id: string; name: string; type: string | null; attack_mod: number | null; damage: string | null; range: string | null; ammo_current: number | null; ammo_max: number | null; status: string | null; notes: string | null; sort_order: number; updated_at: number; } export function listShips(): Pick[] { return db .prepare('SELECT id, name, updated_at FROM ships ORDER BY updated_at DESC') .all() as Pick[]; } export function getShip(id: string): { ship: Ship; weapons: Weapon[] } | null { const ship = db.prepare('SELECT * FROM ships WHERE id = ?').get(id) as Ship | undefined; if (!ship) return null; const weapons = db .prepare('SELECT * FROM weapons WHERE ship_id = ? ORDER BY sort_order ASC, name ASC') .all(id) as Weapon[]; return { ship, weapons }; } export function createShip(input: CreateShipInput): Ship { const id = uuid(); const now = Date.now(); db.prepare(` INSERT INTO ships (id, name, hull_current, hull_max, armor_current, armor_max, ac, con_save, speed, maneuver_class, size_category, notes, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( id, input.name, input.hull_current, input.hull_max, input.armor_current, input.armor_max, input.ac, input.con_save, input.speed, input.maneuver_class, input.size_category, input.notes, now, ); return db.prepare('SELECT * FROM ships WHERE id = ?').get(id) as Ship; } export function updateShip(id: string, patch: UpdateShipInput): Ship | null { const existing = db.prepare('SELECT * FROM ships WHERE id = ?').get(id) as Ship | undefined; if (!existing) return null; const fields = Object.keys(patch).filter( (k) => (patch as Record)[k] !== undefined, ); if (fields.length === 0) return existing; // Validate current <= max against existing values when only one side is patched const newHullCurrent = patch.hull_current ?? existing.hull_current; const newHullMax = patch.hull_max ?? existing.hull_max; const newArmorCurrent = patch.armor_current ?? existing.armor_current; const newArmorMax = patch.armor_max ?? existing.armor_max; if (newHullCurrent > newHullMax) { throw new Error('hull_current cannot exceed hull_max'); } if (newArmorCurrent > newArmorMax) { throw new Error('armor_current cannot exceed armor_max'); } const sets = fields.map((f) => `${f} = ?`); sets.push('updated_at = ?'); const values = fields.map((f) => (patch as Record)[f]); values.push(Date.now()); values.push(id); db.prepare(`UPDATE ships SET ${sets.join(', ')} WHERE id = ?`).run(...values); return db.prepare('SELECT * FROM ships WHERE id = ?').get(id) as Ship; } export function deleteShip(id: string): boolean { const result = db.prepare('DELETE FROM ships WHERE id = ?').run(id); return result.changes > 0; }