import { d as db, u as uploadProgress, b as backups } from '../../admin/create-upload-progress-table/POST-C-OoiMoW.js';
import { eq } from 'drizzle-orm';
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { a as getTempDir, e as ensureDir, g as getBackupsDir } from '../../auth/setup/POST-DYMc2GPx.js';

const upload = multer({
  storage: multer.memoryStorage(),
  limits: {
    fileSize: 100 * 1024 * 1024
    // 100 MB per chunk
  },
  fileFilter: (req, file, cb) => {
    if (file.originalname.includes("/") || file.originalname.includes("\\")) {
      const parts = file.originalname.split(/[\\/]/);
      file.originalname = parts[parts.length - 1];
      console.log("⚠️ [UPLOAD-CHUNK] Sanitized filename with path separators:", file.originalname);
    }
    cb(null, true);
  }
});
async function handler(req, res) {
  console.log("📤 [UPLOAD-CHUNK] Request received");
  console.log("📤 [UPLOAD-CHUNK] Headers:", JSON.stringify(req.headers, null, 2));
  console.log("📤 [UPLOAD-CHUNK] Body fields:", Object.keys(req.body));
  upload.single("chunk")(req, res, async (err) => {
    if (err instanceof multer.MulterError) {
      console.error("❌ [UPLOAD-CHUNK] Multer error:", {
        code: err.code,
        message: err.message,
        field: err.field
      });
      return res.status(400).json({
        success: false,
        error: `Upload error: ${err.message}`,
        code: err.code
      });
    } else if (err) {
      console.error("❌ [UPLOAD-CHUNK] Upload error:", err.message);
      console.error("❌ [UPLOAD-CHUNK] Error stack:", err.stack);
      return res.status(400).json({
        success: false,
        error: err.message
      });
    }
    try {
      const { deviceId, backupId, chunkIndex, totalChunks, fileName, backupType = "full", metadata } = req.body;
      const chunk = req.file;
      console.log("📤 [UPLOAD-CHUNK] Parsed data:", {
        deviceId,
        backupId,
        chunkIndex,
        totalChunks,
        fileName,
        backupType,
        hasChunk: !!chunk,
        chunkSize: chunk?.size
      });
      if (!chunk) {
        console.error("❌ [UPLOAD-CHUNK] No chunk in request");
        console.error("❌ [UPLOAD-CHUNK] Request headers:", JSON.stringify(req.headers, null, 2));
        console.error("❌ [UPLOAD-CHUNK] Content-Type:", req.headers["content-type"]);
        console.error("❌ [UPLOAD-CHUNK] Body keys:", Object.keys(req.body));
        return res.status(400).json({
          success: false,
          error: "No chunk uploaded - file may have been rejected by parser",
          hint: "Check if filename contains path separators (/ or \\\\) - this may cause silent rejection"
        });
      }
      if (!deviceId || !backupId || chunkIndex === void 0 || !totalChunks || !fileName) {
        console.error("❌ [UPLOAD-CHUNK] Missing required fields:", { deviceId, backupId, chunkIndex, totalChunks, fileName });
        return res.status(400).json({
          success: false,
          error: "Missing required fields: deviceId, backupId, chunkIndex, totalChunks, and fileName are required"
        });
      }
      const SAFE_ID = /^[a-zA-Z0-9_-]{1,128}$/;
      if (!SAFE_ID.test(deviceId) || !SAFE_ID.test(backupId)) {
        console.error("❌ [UPLOAD-CHUNK] Invalid deviceId or backupId format");
        return res.status(400).json({
          success: false,
          error: "Invalid deviceId or backupId: only letters, numbers, hyphens, and underscores are allowed"
        });
      }
      const chunkIdx = parseInt(chunkIndex);
      const totalChunksNum = parseInt(totalChunks);
      console.log(`✅ [UPLOAD-CHUNK] Processing chunk ${chunkIdx + 1}/${totalChunksNum} for backup ${backupId}`);
      const tempDir = path.join(getTempDir(), "chunks", deviceId, backupId);
      const resolvedTempDir = path.resolve(tempDir);
      const resolvedBase = path.resolve(path.join(getTempDir(), "chunks"));
      if (!resolvedTempDir.startsWith(resolvedBase + path.sep)) {
        console.error("❌ [UPLOAD-CHUNK] Path traversal detected");
        return res.status(400).json({ success: false, error: "Invalid path" });
      }
      ensureDir(tempDir);
      console.log(`📁 [UPLOAD-CHUNK] Temp directory: ${tempDir}`);
      const chunkPath = path.join(tempDir, `chunk_${chunkIdx}`);
      fs.writeFileSync(chunkPath, chunk.buffer);
      console.log(`💾 [UPLOAD-CHUNK] Saved chunk to: ${chunkPath} (${chunk.size} bytes)`);
      const existingProgress = await db.select().from(uploadProgress).where(eq(uploadProgress.backupId, backupId)).limit(1);
      if (existingProgress.length === 0) {
        console.log(`📊 [UPLOAD-CHUNK] Creating new progress record for backup ${backupId}`);
        await db.insert(uploadProgress).values({
          backupId,
          deviceId,
          fileName,
          totalChunks: totalChunksNum,
          uploadedChunks: 1,
          uploadedSize: chunk.size
        });
      } else {
        const newCount = existingProgress[0].uploadedChunks + 1;
        const newSize = existingProgress[0].uploadedSize + chunk.size;
        console.log(`📊 [UPLOAD-CHUNK] Updating progress: ${newCount}/${totalChunksNum} chunks, ${newSize} bytes`);
        await db.update(uploadProgress).set({
          uploadedChunks: newCount,
          uploadedSize: newSize,
          updatedAt: /* @__PURE__ */ new Date()
        }).where(eq(uploadProgress.backupId, backupId));
      }
      const receivedChunks = fs.readdirSync(tempDir).filter((f) => f.startsWith("chunk_"));
      const isComplete = receivedChunks.length === totalChunksNum;
      console.log(`🔍 [UPLOAD-CHUNK] Progress check: ${receivedChunks.length}/${totalChunksNum} chunks received`);
      if (isComplete) {
        console.log(`🎉 [UPLOAD-CHUNK] All chunks received! Starting merge...`);
        const finalDir = path.join(getBackupsDir(), deviceId);
        ensureDir(finalDir);
        const timestamp = Date.now();
        const ext = path.extname(fileName) || ".backup";
        const finalFileName = `${backupId}_${timestamp}${ext}`;
        const finalPath = path.join(finalDir, finalFileName);
        const writeStream = fs.createWriteStream(finalPath);
        for (let i = 0; i < totalChunksNum; i++) {
          const chunkFile = path.join(tempDir, `chunk_${i}`);
          const chunkData = fs.readFileSync(chunkFile);
          writeStream.write(chunkData);
        }
        writeStream.end();
        await new Promise((resolve, reject) => {
          writeStream.on("finish", resolve);
          writeStream.on("error", reject);
        });
        const stats = fs.statSync(finalPath);
        const fileSize = stats.size;
        fs.rmSync(tempDir, { recursive: true, force: true });
        let parsedMetadata = null;
        if (metadata) {
          try {
            parsedMetadata = JSON.parse(metadata);
          } catch (e) {
            console.warn("Failed to parse metadata:", e);
          }
        }
        const result = await db.insert(backups).values({
          backupId,
          deviceId,
          backupType,
          status: "completed",
          size: Math.floor(fileSize / (1024 * 1024)),
          // Convert to MB
          filePath: finalPath,
          metadata: parsedMetadata ? JSON.stringify(parsedMetadata) : null,
          startedAt: /* @__PURE__ */ new Date(),
          completedAt: /* @__PURE__ */ new Date()
        });
        const insertId = Number(result[0].insertId);
        const newBackup = await db.select().from(backups).where(eq(backups.id, insertId)).limit(1);
        await db.update(uploadProgress).set({
          status: "completed",
          completedAt: /* @__PURE__ */ new Date(),
          totalSize: fileSize
        }).where(eq(uploadProgress.backupId, backupId));
        console.log(`✅ [UPLOAD-CHUNK] Backup completed successfully: ${finalPath}`);
        res.status(201).json({
          success: true,
          chunkIndex: chunkIdx,
          received: true,
          complete: true,
          backup: newBackup[0],
          message: "Backup uploaded successfully"
        });
      } else {
        console.log(`⏳ [UPLOAD-CHUNK] Waiting for more chunks: ${receivedChunks.length}/${totalChunksNum}`);
        res.json({
          success: true,
          chunkIndex: chunkIdx,
          received: true,
          complete: false,
          receivedChunks: receivedChunks.length,
          totalChunks: totalChunksNum
        });
      }
    } catch (error) {
      console.error("❌ [UPLOAD-CHUNK] Fatal error:", error);
      console.error("❌ [UPLOAD-CHUNK] Stack:", error instanceof Error ? error.stack : "No stack");
      res.status(500).json({
        success: false,
        error: "Failed to process chunk upload",
        message: String(error)
      });
    }
  });
}

export { handler as h };
