const express = require("express");
const multer = require("multer");
const sharp = require("sharp");
const cors = require("cors");
const path = require("path");
const fs = require("fs");
require("dotenv").config();

const app = express();
const port = process.env.HTTP_PORT || 3001;
const host = process.env.IP || "0.0.0.0";

// Trust proxy - required when behind Infomaniak's reverse proxy
app.set("trust proxy", true);

// Enable CORS for all routes
app.use(
  cors({
    origin: "*",
    methods: ["GET", "POST", "DELETE", "UPDATE", "PUT", "PATCH"],
    allowedHeaders: ["Content-Type", "Authorization"]
  })
);

// Error handling middleware
app.use((err, req, res, next) => {
  console.error("Error:", err.stack);
  res.status(500).json({ error: "Something went wrong!" });
});

// Middleware
app.use(express.json());

// Create uploads directory if it doesn't exist
const uploadsDir = path.join(__dirname, "../uploads");
try {
  if (!fs.existsSync(uploadsDir)) {
    fs.mkdirSync(uploadsDir, { recursive: true });
  }
} catch (error) {
  console.error("Error creating uploads directory:", error);
}

app.use("/uploads", express.static(path.join(__dirname, "../uploads")));

// Configure multer for file upload
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, uploadsDir);
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
    cb(null, uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB limit
  },
  fileFilter: (req, file, cb) => {
    if (!file.originalname.match(/\.(jpg|jpeg|png|gif|webp)$/)) {
      return cb(new Error("Only image files are allowed!"));
    }
    cb(null, true);
  }
});

// CRUD Routes

// Create - Upload and process image
app.post("/api/images", upload.single("file"), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: "No image file provided" });
    }

    console.log("Received file:", req.file);
    let finalPath = req.file.path;
    let metadata;

    try {
      // Only process non-WebP images
      if (!req.file.originalname.toLowerCase().endsWith(".webp")) {
        console.log("Processing non-WebP image...");
        const image = sharp(req.file.path);
        metadata = await image.metadata();

        // Optimize and convert to WebP
        await image
          .resize(1920, 1080, {
            fit: "inside",
            withoutEnlargement: true
          })
          .webp({ quality: 85 })
          .toFile(req.file.path.replace(/\.[^/.]+$/, ".webp"));

        // Delete original file
        try {
          fs.unlinkSync(req.file.path);
        } catch (unlinkError) {
          console.error("Error deleting original file:", unlinkError);
        }
        finalPath = req.file.path.replace(/\.[^/.]+$/, ".webp");
      } else {
        console.log("File is already WebP, skipping processing");
        metadata = await sharp(req.file.path).metadata();
      }

      const baseUrl = process.env.SERVER_URL || `https://${req.get("host")}`;
      const imageUrl = `${baseUrl}/uploads/${path.basename(finalPath)}`;
      console.log("Image URL:", imageUrl);

      res.json({
        url: imageUrl,
        filename: path.basename(finalPath),
        metadata: {
          width: metadata.width,
          height: metadata.height,
          format: "webp",
          size: metadata.size
        }
      });
    } catch (error) {
      console.error("Error processing image:", error);
      // Clean up the uploaded file if there's an error
      if (fs.existsSync(req.file.path)) {
        try {
          fs.unlinkSync(req.file.path);
        } catch (unlinkError) {
          console.error("Error deleting file during cleanup:", unlinkError);
        }
      }
      throw error;
    }
  } catch (error) {
    console.error("Upload error:", error);
    res.status(500).json({ error: "Error processing image: " + error.message });
  }
});

// Read - Get image info
app.get("/api/images/:filename", async (req, res) => {
  try {
    const filename = req.params.filename;
    const filepath = path.join(uploadsDir, filename);

    const stats = fs.statSync(filepath);
    const metadata = await sharp(filepath).metadata();

    res.json({
      filename,
      url: `https://${req.get("host")}/uploads/${filename}`,
      metadata: {
        width: metadata.width,
        height: metadata.height,
        format: metadata.format,
        size: stats.size
      }
    });
  } catch (error) {
    res.status(404).json({ error: "Image not found" });
  }
});

// Read - List all images
app.get("/api/images", async (req, res) => {
  try {
    const files = fs.readdirSync(uploadsDir);
    const images = files.filter((file) =>
      file.match(/\.(jpg|jpeg|png|gif|webp)$/)
    );

    const imageList = images.map((filename) => ({
      filename,
      url: `https://${req.get("host")}/uploads/${filename}`
    }));

    res.json(imageList);
  } catch (error) {
    res.status(500).json({ error: "Error listing images" });
  }
});

// Delete image
app.delete("/api/images/:filename", async (req, res) => {
  try {
    const filename = req.params.filename;
    const filepath = path.join(uploadsDir, filename);

    fs.unlinkSync(filepath);
    res.json({ message: "Image deleted successfully" });
  } catch (error) {
    res.status(404).json({ error: "Image not found" });
  }
});

// Health check endpoint
app.get("/health", (req, res) => {
  res.json({ status: "ok" });
});

// Start HTTP server - explicitly use the host variable
app.listen(port, host, () => {
  console.log(`Server running on ${host}:${port}`);
  console.log(`Uploads directory: ${uploadsDir}`);
}).on('error', (err) => {
  console.error('Server error:', err);
  process.exit(1);
});
