"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.taskQuerySchema = exports.syncQuerySchema = exports.pushChangesSchema = exports.tombstoneSchema = exports.friendshipSchema = exports.friendRequestSchema = exports.searchQuerySchema = exports.repeatProfileUpdateSchema = exports.repeatProfileSchema = exports.userSettingsSchema = exports.subtaskUpdateSchema = exports.subtaskCreateSchema = exports.taskUpdateSchema = exports.taskCreateSchema = exports.repeatIntervalFieldSchema = exports.repeatFieldSchema = exports.repeatSchema = exports.categoryUpdateSchema = exports.categoryCreateSchema = void 0;
exports.canCompleteTask = canCompleteTask;
const zod_1 = require("zod");
function canCompleteTask(dueDate) {
    if (dueDate === 0)
        return true;
    const now = new Date();
    const endOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999).getTime();
    return dueDate <= endOfToday;
}
exports.categoryCreateSchema = zod_1.z.object({
    name: zod_1.z.string().min(1).max(50),
    color: zod_1.z.string().regex(/^#[0-9A-Fa-f]{6}$/),
    order: zod_1.z.number().int().min(0).optional(),
});
exports.categoryUpdateSchema = zod_1.z.object({
    name: zod_1.z.string().min(1).max(50).optional(),
    color: zod_1.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
    order: zod_1.z.number().int().min(0).optional(),
});
exports.repeatSchema = zod_1.z.enum(['none', 'daily', 'weekly', 'monthly', 'custom']);
// The client stores '' / 0 for unset repeat values; normalize them so stale or
// legacy rows never fail validation on push.
exports.repeatFieldSchema = exports.repeatSchema
    .or(zod_1.z.literal(''))
    .transform((v) => (v === '' ? 'none' : v))
    .optional();
exports.repeatIntervalFieldSchema = zod_1.z
    .number()
    .int()
    .min(0)
    .max(30)
    .transform((v) => Math.max(1, v))
    .optional();
exports.taskCreateSchema = zod_1.z.object({
    title: zod_1.z.string().min(1).max(100),
    description: zod_1.z.string().max(1000).optional(),
    categoryId: zod_1.z.string().max(100).transform((v) => (v === '' ? null : v)).nullable(),
    priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
    dueDate: zod_1.z.number().int().min(0).optional(),
    dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v ?? ''),
    endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')),
    allDay: zod_1.z.boolean().optional(),
    repeat: exports.repeatFieldSchema,
    repeatInterval: exports.repeatIntervalFieldSchema,
    repeatDays: zod_1.z.string().max(20).optional(),
    seriesId: zod_1.z.string().max(50).optional(),
    reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
    reminders: zod_1.z.string().max(100).optional(),
    assigneeId: zod_1.z.string().nullable().optional(),
    completedAt: zod_1.z.number().int().min(0).nullable().optional(),
    subtasks: zod_1.z.array(zod_1.z.object({ title: zod_1.z.string().min(1).max(100) })).optional(),
});
exports.taskUpdateSchema = zod_1.z.object({
    title: zod_1.z.string().min(1).max(100).optional(),
    description: zod_1.z.string().max(1000).optional(),
    categoryId: zod_1.z.string().max(100).nullable().optional().transform((v) => (v === '' ? null : v)),
    priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
    completed: zod_1.z.boolean().optional(),
    dueDate: zod_1.z.number().int().min(0).optional(),
    dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v === '' ? undefined : v),
    endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
    reminders: zod_1.z.string().max(100).optional(),
    assigneeId: zod_1.z.string().nullable().optional(),
    completedAt: zod_1.z.number().int().min(0).nullable().optional(),
});
exports.subtaskCreateSchema = zod_1.z.object({
    title: zod_1.z.string().min(1).max(100),
    description: zod_1.z.string().max(1000).optional(),
    priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
    dueDate: zod_1.z.number().int().min(0).optional(),
    dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v ?? ''),
    endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')),
    allDay: zod_1.z.boolean().optional(),
    repeat: exports.repeatFieldSchema,
    repeatInterval: exports.repeatIntervalFieldSchema,
    repeatDays: zod_1.z.string().max(20).optional(),
    seriesId: zod_1.z.string().max(50).optional(),
    reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
    reminders: zod_1.z.string().max(100).optional(),
    assigneeId: zod_1.z.string().nullable().optional(),
    order: zod_1.z.number().int().min(0).optional(),
    parentSubtaskId: zod_1.z.string().nullable().optional(),
});
exports.subtaskUpdateSchema = zod_1.z.object({
    title: zod_1.z.string().min(1).max(100).optional(),
    description: zod_1.z.string().max(1000).optional(),
    priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
    completed: zod_1.z.boolean().optional(),
    dueDate: zod_1.z.number().int().min(0).optional(),
    dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v === '' ? undefined : v),
    endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
    allDay: zod_1.z.boolean().optional(),
    repeat: exports.repeatFieldSchema,
    repeatInterval: exports.repeatIntervalFieldSchema,
    repeatDays: zod_1.z.string().max(20).optional(),
    seriesId: zod_1.z.string().max(50).optional(),
    reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
    reminders: zod_1.z.string().max(100).optional(),
    assigneeId: zod_1.z.string().nullable().optional(),
    order: zod_1.z.number().int().min(0).optional(),
    parentSubtaskId: zod_1.z.string().nullable().optional(),
});
exports.userSettingsSchema = zod_1.z.object({
    darkMode: zod_1.z.boolean().optional(),
    notifications: zod_1.z.boolean().optional(),
    reminderTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
    defaultCategory: zod_1.z.string().optional().nullable(),
    sortBy: zod_1.z.enum(['dueDate', 'priority', 'title', 'createdAt']).optional(),
    sortOrder: zod_1.z.enum(['asc', 'desc']).optional(),
});
exports.repeatProfileSchema = zod_1.z.object({
    name: zod_1.z.string().min(1).max(50),
    repeat: exports.repeatSchema,
    repeatInterval: zod_1.z.number().int().min(1).max(30),
    repeatDays: zod_1.z.string().max(20),
});
exports.repeatProfileUpdateSchema = zod_1.z.object({
    name: zod_1.z.string().min(1).max(50).optional(),
    repeat: exports.repeatSchema.optional(),
    repeatInterval: zod_1.z.number().int().min(1).max(30).optional(),
    repeatDays: zod_1.z.string().max(20).optional(),
});
exports.searchQuerySchema = zod_1.z.object({
    q: zod_1.z.string().min(1).max(50),
});
exports.friendRequestSchema = zod_1.z.object({
    username: zod_1.z.string().min(1).max(50),
});
exports.friendshipSchema = zod_1.z.object({
    id: zod_1.z.string(),
    userId: zod_1.z.string(),
    friendId: zod_1.z.string(),
    status: zod_1.z.enum(['pending', 'accepted']),
    createdAt: zod_1.z.number(),
    updatedAt: zod_1.z.number(),
});
exports.tombstoneSchema = zod_1.z.object({
    entity: zod_1.z.enum(['categories', 'tasks', 'subtasks', 'repeatProfiles', 'friendships']),
    id: zod_1.z.string(),
    updatedAt: zod_1.z.number().int().min(0),
});
exports.pushChangesSchema = zod_1.z.object({
    changes: zod_1.z.object({
        categories: zod_1.z.array(exports.categoryCreateSchema.extend({ id: zod_1.z.string(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(),
        tasks: zod_1.z.array(exports.taskCreateSchema.extend({ id: zod_1.z.string(), completed: zod_1.z.boolean(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number(), completedAt: zod_1.z.number().int().min(0).nullable().optional() })).optional(),
        subtasks: zod_1.z.array(exports.subtaskCreateSchema.extend({ id: zod_1.z.string(), taskId: zod_1.z.string(), completed: zod_1.z.boolean(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(),
        repeatProfiles: zod_1.z.array(exports.repeatProfileSchema.extend({ id: zod_1.z.string(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(),
        friendships: zod_1.z.array(exports.friendshipSchema).optional(),
    }),
    deleted: zod_1.z.array(exports.tombstoneSchema).optional(),
    lastPulledAt: zod_1.z.number().int().min(0),
});
exports.syncQuerySchema = zod_1.z.object({
    since: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)),
});
exports.taskQuerySchema = zod_1.z.object({
    categoryId: zod_1.z.string().optional(),
    completed: zod_1.z.string().transform(v => v === 'true').optional(),
    dueBefore: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)).optional(),
    dueAfter: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)).optional(),
    priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
    sortBy: zod_1.z.enum(['dueDate', 'priority', 'createdAt', 'title']).optional(),
    sortOrder: zod_1.z.enum(['asc', 'desc']).optional(),
    limit: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(1).max(100)).optional(),
    offset: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)).optional(),
});
//# sourceMappingURL=validation.js.map