File size: 3,110 Bytes
79c5a92
 
9a9e7ec
 
79c5a92
 
 
 
 
 
 
 
 
492565a
 
79c5a92
492565a
 
 
 
79c5a92
 
 
 
 
 
 
492565a
79c5a92
 
492565a
79c5a92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a9e7ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79c5a92
9a9e7ec
 
 
79c5a92
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
const { getSession } = require('../services/sessionManager');
const { generateQuotePDF } = require('../services/pdfService');
const { generateSignedUploadUrl } = require('../services/storageService');
const { validateImageSize } = require('../engine/imageProcessor');

/**
 * Handles requests for generating a PDF quote based on a user's cart.
 */
async function handlePdfQuote(req, res) {
    const { userId, cart: clientCart } = req.body;

    // Fetch cart from body, or fallback to server session state
    let cart = clientCart;
    let isDraft = false;
    if (userId) {
        const session = getSession(userId);
        if (!cart) cart = session.cart;
        if (session.draftAttributes && Object.keys(session.draftAttributes).length > 0) {
            isDraft = true;
        }
    }

    if (!cart || cart.length === 0) {
        return res.status(400).send("ื”ืขื’ืœื” ืจื™ืงื”");
    }

    try {
        console.log(`๐Ÿ“„ Generating PDF Quote (isDraft: ${isDraft}) via DocumentController...`);

        // Build PDF Buffer
        const pdfBuffer = await generateQuotePDF(cart, { name: "ืœืงื•ื— ื™ืงืจ" }, isDraft);

        // Define headers for file download
        res.set({
            'Content-Type': 'application/pdf',
            'Content-Length': pdfBuffer.length,
            'Content-Disposition': 'attachment; filename="quote.pdf"'
        });

        // Send file
        res.send(pdfBuffer);
        console.log("โœ… PDF sent successfully to client");

    } catch (error) {
        console.error("โŒ DocumentController Error:", error);
        res.status(500).json({ error: "Failed to generate PDF" });
    }
}

/**
 * Generates a signed URL for direct GCP upload.
 * Validates session and file size (client-reported) before granting URL.
 */
async function handleSignedUrl(req, res) {
    const { userId, fileName, fileSize } = req.body;

    if (!userId || !fileName || !fileSize) {
        return res.status(400).json({ error: "Missing required parameters (userId, fileName, fileSize)" });
    }

    // 10MB Gatekeeper (Technical size check before granting storage access)
    const MAX_SIZE_BYTES = 10 * 1024 * 1024;
    if (fileSize > MAX_SIZE_BYTES) {
        console.warn(`[IMAGE GATEKEEPER] Rejected ${fileName} due to size: ${fileSize}`);
        return res.status(413).json({
            error: "FILE_TOO_LARGE",
            message: "ืงื•ื‘ืฅ ื’ื“ื•ืœ ืžื“ื™. ืžืงืกื™ืžื•ื 10MB."
        });
    }

    try {
        const result = await generateSignedUploadUrl(userId, fileName);
        res.json(result);
    } catch (error) {
        res.status(500).json({ error: "Failed to generate signed URL" });
    }
}

/**
 * Technical validator for buffers (for local processing if needed).
 */
async function handleImageValidation(req, res) {
    const { buffer } = req.body; // Assuming small metadata/preview buffer for now
    const check = validateImageSize(buffer);
    if (!check.valid) {
        return res.status(400).json(check);
    }
    res.json({ valid: true });
}

module.exports = {
    handlePdfQuote,
    handleSignedUrl,
    handleImageValidation
};