import { db } from './db/index.js'; import { randomUUID } from 'crypto'; export type PlanType = | 'destination' | 'activity' | 'transport' | 'lodging' | 'restaurant' | 'tour' | 'packing' | 'todo'; export type PlanStatus = 'idea' | 'tentative' | 'confirmed'; export interface Plan { id: string; trip_id: string; user_id: string; type: PlanType; status: PlanStatus; parent_id: string | null; title: string; notes: string | null; city_id: number | null; city_name: string | null; country: string | null; country_code: string | null; start_date: string | null; end_date: string | null; position: number; created_at: string; updated_at: string; } export interface City { id: number; name: string; country: string; country_code: string; population: number | null; } export interface CreateDestinationInput { tripId: string; userId: string; cityId?: number; cityName: string; country: string; countryCode: string; startDate?: string; endDate?: string; status?: PlanStatus; notes?: string; } export function createDestination(input: CreateDestinationInput): Plan { const id = randomUUID(); const maxPos = db.get<{ pos: number }>( `SELECT COALESCE(MAX(position), -1) + 1 as pos FROM plans WHERE trip_id = ? AND user_id = ?`, [input.tripId, input.userId] ); const position = maxPos?.pos ?? 0; db.run( `INSERT INTO plans (id, trip_id, user_id, type, status, title, notes, city_id, city_name, country, country_code, start_date, end_date, position) VALUES (?, ?, ?, 'destination', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ id, input.tripId, input.userId, input.status ?? 'idea', input.cityName, input.notes ?? null, input.cityId ?? null, input.cityName, input.country, input.countryCode, input.startDate ?? null, input.endDate ?? null, position ] ); return db.get('SELECT * FROM plans WHERE id = ?', [id])!; } export function getPlansForTrip(tripId: string, userId: string): Plan[] { return db.all( `SELECT * FROM plans WHERE trip_id = ? AND user_id = ? ORDER BY position ASC, created_at ASC`, [tripId, userId] ); } export function getPlanCountForTrip(tripId: string, userId: string): number { const row = db.get<{ count: number }>( `SELECT COUNT(*) as count FROM plans WHERE trip_id = ? AND user_id = ?`, [tripId, userId] ); return row?.count ?? 0; } export interface Country { name: string; country_code: string; } export function getCountries(query?: string): Country[] { if (!query?.trim()) { return db.all( `SELECT DISTINCT country as name, country_code FROM cities ORDER BY country` ); } const pattern = `%${query.trim()}%`; return db.all( `SELECT DISTINCT country as name, country_code FROM cities WHERE country LIKE ? COLLATE NOCASE ORDER BY country LIMIT 50`, [pattern] ); } export function searchCities(query: string, countryCode?: string): City[] { if (!query.trim()) return []; const pattern = `%${query.trim()}%`; if (countryCode?.trim()) { return db.all( `SELECT id, name, country, country_code, population FROM cities WHERE name LIKE ? COLLATE NOCASE AND country_code = ? ORDER BY CASE WHEN name LIKE ? COLLATE NOCASE THEN 0 ELSE 1 END, population DESC NULLS LAST LIMIT 10`, [pattern, countryCode.trim().toUpperCase(), `${query.trim()}%`] ); } return db.all( `SELECT id, name, country, country_code, population FROM cities WHERE name LIKE ? COLLATE NOCASE ORDER BY CASE WHEN name LIKE ? COLLATE NOCASE THEN 0 ELSE 1 END, population DESC NULLS LAST LIMIT 10`, [pattern, `${query.trim()}%`] ); } export function deletePlan(planId: string, userId: string): void { // Verify the plan belongs to the user const plan = db.get('SELECT * FROM plans WHERE id = ? AND user_id = ?', [planId, userId]); if (!plan) { throw new Error('Plan not found or not authorized'); } db.run('DELETE FROM plans WHERE id = ?', [planId]); }