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

class LocalStorage {
  basePath;
  constructor(basePath) {
    this.basePath = basePath || getBackupsDir();
    ensureDir(this.basePath);
  }
  async upload(file, filePath, metadata) {
    const fullPath = path.join(this.basePath, filePath);
    const dir = path.dirname(fullPath);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    if (Buffer.isBuffer(file)) {
      fs.writeFileSync(fullPath, file);
    } else {
      const writeStream = fs.createWriteStream(fullPath);
      await new Promise((resolve, reject) => {
        file.pipe(writeStream);
        writeStream.on("finish", resolve);
        writeStream.on("error", reject);
      });
    }
    if (metadata) {
      const metadataPath = `${fullPath}.meta.json`;
      fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
    }
    return fullPath;
  }
  async download(filePath) {
    const fullPath = path.join(this.basePath, filePath);
    if (!fs.existsSync(fullPath)) {
      throw new Error(`File not found: ${filePath}`);
    }
    return fs.readFileSync(fullPath);
  }
  async delete(filePath) {
    const fullPath = path.join(this.basePath, filePath);
    if (fs.existsSync(fullPath)) {
      fs.unlinkSync(fullPath);
      const metadataPath = `${fullPath}.meta.json`;
      if (fs.existsSync(metadataPath)) {
        fs.unlinkSync(metadataPath);
      }
    }
  }
  async exists(filePath) {
    const fullPath = path.join(this.basePath, filePath);
    return fs.existsSync(fullPath);
  }
  async list(prefix) {
    const fullPath = path.join(this.basePath, prefix);
    if (!fs.existsSync(fullPath)) {
      return [];
    }
    const files = [];
    const walk = (dir) => {
      const items = fs.readdirSync(dir);
      for (const item of items) {
        const itemPath = path.join(dir, item);
        const stat = fs.statSync(itemPath);
        if (stat.isDirectory()) {
          walk(itemPath);
        } else if (!item.endsWith(".meta.json")) {
          files.push(path.relative(this.basePath, itemPath));
        }
      }
    };
    walk(fullPath);
    return files;
  }
}
class S3Storage {
  s3Client;
  bucket;
  constructor(config) {
    try {
      const { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, HeadObjectCommand, ListObjectsV2Command } = require("@aws-sdk/client-s3");
      this.s3Client = new S3Client({
        region: config.region,
        credentials: {
          accessKeyId: config.accessKeyId,
          secretAccessKey: config.secretAccessKey
        }
      });
      this.bucket = config.bucket;
    } catch (error) {
      throw new Error("AWS SDK not installed. Run: npm install @aws-sdk/client-s3");
    }
  }
  async upload(file, filePath, metadata) {
    const { PutObjectCommand } = require("@aws-sdk/client-s3");
    const command = new PutObjectCommand({
      Bucket: this.bucket,
      Key: filePath,
      Body: file,
      Metadata: metadata
    });
    await this.s3Client.send(command);
    return `s3://${this.bucket}/${filePath}`;
  }
  async download(filePath) {
    const { GetObjectCommand } = require("@aws-sdk/client-s3");
    const command = new GetObjectCommand({
      Bucket: this.bucket,
      Key: filePath
    });
    const response = await this.s3Client.send(command);
    const chunks = [];
    for await (const chunk of response.Body) {
      chunks.push(chunk);
    }
    return Buffer.concat(chunks);
  }
  async delete(filePath) {
    const { DeleteObjectCommand } = require("@aws-sdk/client-s3");
    const command = new DeleteObjectCommand({
      Bucket: this.bucket,
      Key: filePath
    });
    await this.s3Client.send(command);
  }
  async exists(filePath) {
    const { HeadObjectCommand } = require("@aws-sdk/client-s3");
    try {
      const command = new HeadObjectCommand({
        Bucket: this.bucket,
        Key: filePath
      });
      await this.s3Client.send(command);
      return true;
    } catch (error) {
      if (error.name === "NotFound") {
        return false;
      }
      throw error;
    }
  }
  async list(prefix) {
    const { ListObjectsV2Command } = require("@aws-sdk/client-s3");
    const command = new ListObjectsV2Command({
      Bucket: this.bucket,
      Prefix: prefix
    });
    const response = await this.s3Client.send(command);
    return (response.Contents || []).map((item) => item.Key);
  }
}
class GCSStorage {
  storage;
  bucket;
  constructor(config) {
    try {
      const { Storage } = require("@google-cloud/storage");
      this.storage = new Storage({
        projectId: config.projectId,
        keyFilename: config.keyFilename
      });
      this.bucket = this.storage.bucket(config.bucket);
    } catch (error) {
      throw new Error("Google Cloud Storage SDK not installed. Run: npm install @google-cloud/storage");
    }
  }
  async upload(file, filePath, metadata) {
    const fileRef = this.bucket.file(filePath);
    if (Buffer.isBuffer(file)) {
      await fileRef.save(file, { metadata: { metadata } });
    } else {
      await new Promise((resolve, reject) => {
        file.pipe(fileRef.createWriteStream({ metadata: { metadata } })).on("finish", resolve).on("error", reject);
      });
    }
    return `gs://${this.bucket.name}/${filePath}`;
  }
  async download(filePath) {
    const fileRef = this.bucket.file(filePath);
    const [buffer] = await fileRef.download();
    return buffer;
  }
  async delete(filePath) {
    const fileRef = this.bucket.file(filePath);
    await fileRef.delete();
  }
  async exists(filePath) {
    const fileRef = this.bucket.file(filePath);
    const [exists] = await fileRef.exists();
    return exists;
  }
  async list(prefix) {
    const [files] = await this.bucket.getFiles({ prefix });
    return files.map((file) => file.name);
  }
}
class AzureStorage {
  containerClient;
  constructor(config) {
    try {
      const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob");
      const sharedKeyCredential = new StorageSharedKeyCredential(config.accountName, config.accountKey);
      const blobServiceClient = new BlobServiceClient(
        `https://${config.accountName}.blob.core.windows.net`,
        sharedKeyCredential
      );
      this.containerClient = blobServiceClient.getContainerClient(config.containerName);
    } catch (error) {
      throw new Error("Azure Storage SDK not installed. Run: npm install @azure/storage-blob");
    }
  }
  async upload(file, filePath, metadata) {
    const blockBlobClient = this.containerClient.getBlockBlobClient(filePath);
    if (Buffer.isBuffer(file)) {
      await blockBlobClient.upload(file, file.length, { metadata });
    } else {
      await blockBlobClient.uploadStream(file, void 0, void 0, { metadata });
    }
    return blockBlobClient.url;
  }
  async download(filePath) {
    const blockBlobClient = this.containerClient.getBlockBlobClient(filePath);
    const downloadResponse = await blockBlobClient.download();
    const chunks = [];
    for await (const chunk of downloadResponse.readableStreamBody) {
      chunks.push(chunk);
    }
    return Buffer.concat(chunks);
  }
  async delete(filePath) {
    const blockBlobClient = this.containerClient.getBlockBlobClient(filePath);
    await blockBlobClient.delete();
  }
  async exists(filePath) {
    const blockBlobClient = this.containerClient.getBlockBlobClient(filePath);
    return await blockBlobClient.exists();
  }
  async list(prefix) {
    const files = [];
    for await (const blob of this.containerClient.listBlobsFlat({ prefix })) {
      files.push(blob.name);
    }
    return files;
  }
}
function createStorageProvider(config) {
  switch (config.type) {
    case "local":
      return new LocalStorage(config.config.basePath);
    case "s3":
      return new S3Storage(config.config);
    case "gcs":
      return new GCSStorage(config.config);
    case "azure":
      return new AzureStorage(config.config);
    default:
      throw new Error(`Unknown storage type: ${config.type}`);
  }
}

async function handler(req, res) {
  try {
    const { backupId } = req.params;
    const { deviceId } = req.query;
    if (!backupId) {
      return res.status(400).json({
        success: false,
        error: "Backup ID is required"
      });
    }
    if (!deviceId) {
      return res.status(400).json({
        success: false,
        error: "Device ID is required for authorization"
      });
    }
    const backup = await db.select().from(backups).where(eq(backups.backupId, backupId)).limit(1);
    if (backup.length === 0) {
      return res.status(404).json({
        success: false,
        error: "Backup not found"
      });
    }
    const backupRecord = backup[0];
    if (backupRecord.deviceId !== deviceId) {
      return res.status(403).json({
        success: false,
        error: "Unauthorized: Backup belongs to different device"
      });
    }
    const configs = await db.select().from(storageConfig).where(eq(storageConfig.isActive, true)).orderBy(desc(storageConfig.createdAt)).limit(1);
    let storageType = "local";
    let storageConfigData = { basePath: getBackupsDir() };
    if (configs.length > 0) {
      storageType = configs[0].storageType;
      storageConfigData = JSON.parse(configs[0].config);
    }
    const storageProvider = createStorageProvider({
      type: storageType,
      config: storageConfigData
    });
    const storagePath = backupRecord.filePath;
    if (storagePath) {
      try {
        const exists = await storageProvider.exists(storagePath);
        if (exists) {
          await storageProvider.delete(storagePath);
        }
      } catch (error) {
        console.error("Failed to delete file from storage:", error);
      }
    }
    await db.delete(backups).where(eq(backups.backupId, backupId));
    res.json({
      success: true,
      message: "Backup deleted successfully"
    });
  } catch (error) {
    console.error("Backup deletion error:", error);
    res.status(500).json({
      success: false,
      error: "Failed to delete backup",
      message: String(error)
    });
  }
}

export { createStorageProvider as c, handler as h };
