import { getPrismaClient } from '../db/prisma.js';
import { createLogger } from '@4runr/shared';
import { z } from 'zod';
import { requireAuth } from '../middleware/auth.js';
import { writeRateLimit, strictRateLimit } from '../middleware/rateLimit.js';
const logger = createLogger('Gateway:Routes:GDPR');
function assertGdprSubject(request, userId, reply) {
    const auth = request.auth ||
        request.user;
    if (auth?.sub && auth.sub !== userId) {
        reply.status(403).send({
            error: 'forbidden',
            message: 'userId does not match authenticated identity',
        });
        return false;
    }
    return true;
}
const deleteDataSchema = z.object({
    userId: z.string().uuid(),
    confirm: z.boolean().refine(val => val === true, {
        message: 'Must confirm deletion'
    })
});
const exportDataSchema = z.object({
    userId: z.string().uuid()
});
export async function gdprRoutes(fastify) {
    logger.info('Registering GDPR routes...');
    fastify.post('/api/gdpr/export', {
        preHandler: [requireAuth, writeRateLimit],
    }, async (request, reply) => {
        try {
            const body = exportDataSchema.parse(request.body);
            if (!assertGdprSubject(request, body.userId, reply))
                return;
            const prisma = await getPrismaClient();
            const user = await prisma.user.findUnique({
                where: { id: body.userId },
                include: {
                    roles: {
                        include: {
                            role: true
                        }
                    },
                    apiKeys: true,
                    sessions: true
                }
            });
            if (!user) {
                return reply.status(404).send({
                    error: 'not_found',
                    message: 'User not found'
                });
            }
            const apiKeyIds = user.apiKeys.map(k => k.id);
            const chatHistory = await prisma.chatHistory.findMany({
                where: {
                    clientId: body.userId
                }
            });
            const exportData = {
                user: {
                    id: user.id,
                    email: user.email,
                    username: user.username,
                    status: user.status,
                    createdAt: user.createdAt,
                    updatedAt: user.updatedAt,
                    lastLoginAt: user.lastLoginAt,
                    mfaEnabled: user.mfaEnabled
                },
                roles: user.roles.map(ur => ({
                    role: ur.role.name,
                    assignedAt: ur.assignedAt
                })),
                apiKeys: user.apiKeys.map(k => ({
                    id: k.id,
                    label: k.label,
                    createdAt: k.createdAt,
                    revoked: k.revoked,
                    revokedAt: k.revokedAt
                })),
                sessions: user.sessions.map(s => ({
                    id: s.id,
                    ipAddress: s.ipAddress,
                    userAgent: s.userAgent,
                    createdAt: s.createdAt,
                    lastActivityAt: s.lastActivityAt,
                    expiresAt: s.expiresAt
                })),
                chatHistory: chatHistory.map(ch => ({
                    id: ch.id,
                    agentName: ch.agentName,
                    messages: ch.messages,
                    createdAt: ch.createdAt,
                    lastMessageAt: ch.lastMessageAt
                })),
                exportedAt: new Date().toISOString(),
                format: 'json',
                version: '1.0'
            };
            return reply.send(exportData);
        }
        catch (error) {
            logger.error('Error exporting user data', { error: error.message });
            if (error instanceof z.ZodError) {
                return reply.status(400).send({
                    error: 'invalid_request',
                    message: 'Invalid request body',
                    details: error.errors
                });
            }
            return reply.status(500).send({
                error: 'internal_error',
                message: 'Failed to export user data'
            });
        }
    });
    fastify.post('/api/gdpr/delete', {
        preHandler: [requireAuth, strictRateLimit],
    }, async (request, reply) => {
        try {
            const body = deleteDataSchema.parse(request.body);
            if (!assertGdprSubject(request, body.userId, reply))
                return;
            const prisma = await getPrismaClient();
            const user = await prisma.user.findUnique({
                where: { id: body.userId },
                include: {
                    apiKeys: true,
                    sessions: true
                }
            });
            if (!user) {
                return reply.status(404).send({
                    error: 'not_found',
                    message: 'User not found'
                });
            }
            await prisma.userSession.deleteMany({
                where: { userId: body.userId }
            });
            await prisma.apiKey.deleteMany({
                where: { userId: body.userId }
            });
            await prisma.userRole.deleteMany({
                where: { userId: body.userId }
            });
            await prisma.chatHistory.deleteMany({
                where: { clientId: body.userId }
            });
            await prisma.user.update({
                where: { id: body.userId },
                data: {
                    status: 'DELETED',
                    email: `deleted_${body.userId}@deleted.local`,
                    username: `deleted_${body.userId}`,
                    passwordHash: null,
                    mfaSecret: null,
                    mfaBackupCodes: [],
                    mfaEnabled: false
                }
            });
            logger.info('User data deleted (GDPR)', { userId: body.userId });
            return reply.send({
                deleted: true,
                message: 'User data deleted successfully',
                deletedAt: new Date().toISOString()
            });
        }
        catch (error) {
            logger.error('Error deleting user data', { error: error.message });
            if (error instanceof z.ZodError) {
                return reply.status(400).send({
                    error: 'invalid_request',
                    message: 'Invalid request body',
                    details: error.errors
                });
            }
            return reply.status(500).send({
                error: 'internal_error',
                message: 'Failed to delete user data'
            });
        }
    });
    fastify.post('/api/gdpr/retention/cleanup', {
        preHandler: [requireAuth, strictRateLimit],
    }, async (request, reply) => {
        try {
            const prisma = await getPrismaClient();
            const now = new Date();
            const RETENTION_POLICIES = {
                runs: parseInt(process.env['GDPR_RETENTION_RUNS_DAYS'] || '365'),
                chatHistory: parseInt(process.env['GDPR_RETENTION_CHAT_DAYS'] || '90'),
                sessions: parseInt(process.env['GDPR_RETENTION_SESSIONS_DAYS'] || '30'),
                logs: parseInt(process.env['GDPR_RETENTION_LOGS_DAYS'] || '90')
            };
            const results = {
                runsDeleted: 0,
                chatHistoryDeleted: 0,
                sessionsDeleted: 0,
                deletedAt: now.toISOString()
            };
            const runsCutoff = new Date(now.getTime() - RETENTION_POLICIES.runs * 24 * 60 * 60 * 1000);
            const deletedRuns = await prisma.run.deleteMany({
                where: {
                    createdAt: {
                        lt: runsCutoff
                    }
                }
            });
            results.runsDeleted = deletedRuns.count;
            const chatCutoff = new Date(now.getTime() - RETENTION_POLICIES.chatHistory * 24 * 60 * 60 * 1000);
            const deletedChat = await prisma.chatHistory.deleteMany({
                where: {
                    lastMessageAt: {
                        lt: chatCutoff
                    }
                }
            });
            results.chatHistoryDeleted = deletedChat.count;
            const sessionCutoff = new Date(now.getTime() - RETENTION_POLICIES.sessions * 24 * 60 * 60 * 1000);
            const deletedSessions = await prisma.userSession.deleteMany({
                where: {
                    OR: [
                        { expiresAt: { lt: now } },
                        { lastActivityAt: { lt: sessionCutoff } }
                    ]
                }
            });
            results.sessionsDeleted = deletedSessions.count;
            logger.info('GDPR retention cleanup completed', results);
            return reply.send({
                success: true,
                results,
                retentionPolicies: RETENTION_POLICIES
            });
        }
        catch (error) {
            logger.error('Error running retention cleanup', { error: error.message });
            return reply.status(500).send({
                error: 'internal_error',
                message: 'Failed to run retention cleanup'
            });
        }
    });
    logger.info('GDPR routes registration completed', {
        routes: ['/api/gdpr/export', '/api/gdpr/delete', '/api/gdpr/retention/cleanup']
    });
}
//# sourceMappingURL=gdpr.js.map