const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const cors = require('cors');
const crypto = require('crypto');
const express = require('express');
const fs = require('fs');
const multer = require('multer');
const path = require('path');
const sqlite3 = require('sqlite3').verbose();
require('dotenv').config()

const app = express();
app.use(cors());

const port = process.env.PORT || 3000;
const dbFile = process.env.SQLITE_FILE || './sqlite-db.sqlite';

// Open a connection to the SQLite database
const db = new sqlite3.Database(dbFile, (err) => {
  if (err) {
    console.error('Error opening database:', err);
  }
});

// Configure AWS
const s3Client = new S3Client({
  region: process.env.AWS_REGION,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY,
    secretAccessKey: process.env.AWS_SECRET_KEY
  }
});

const uploadDir = 'uploads';
const uploadMulter = multer({ dest: uploadDir + '/' });

// POST endpoint to upload an image
app.post('/image', uploadMulter.single('image'), (req, res) => {
  const file = req.file;

  // Read the file from the temporary location
  fs.readFile(file.path, async (err, data) => {
    if (err) throw err; // Handle error

    const hashSum = crypto.createHash('sha256');
    hashSum.update(data);
    const hashHex = hashSum.digest('hex');

    const bucketName = 'gifts-image';
    const fileName = hashHex;
    const params = {
      Body: data,
      Bucket: bucketName, // S3 Bucket name
      ContentType: file.mimetype, // File content type
      Key: fileName, // File name to use in S3
    };

    // Upload the file to S3
    try {

      // record the upload in the database
      const currentDate = new Date().toISOString();
      const localFile = file.path.startsWith(uploadDir + '/') ? file.path.substring(uploadDir.length + 1) : file.path;
      const finalUrl = `https://${bucketName}.s3.amazonaws.com/${fileName}`;
      db.run('INSERT INTO image (date, did, local_file, size, aws_file, url) VALUES (?, ?, ?, ?, ?, ?)', [
        currentDate,
        "UNKNOWN",
        localFile,
        file.size,
        fileName,
        finalUrl
      ], (dbErr) => {
        if (dbErr) {
          console.error(currentDate, "Error inserting record from", "UNKNOWN", "into database:", dbErr);
        }
      });

      // send to AWS
      const command = new PutObjectCommand(params);
      const response = await s3Client.send(command);
      if (response.$metadata.httpStatusCode !== 200) {
        const errorTime = new Date().toISOString();
        console.error(errorTime, "Error uploading to S3 with bad HTTP status. Metadata:", response.$metadata);
        res.status(500).send(JSON.stringify({ success: false, message: "Got bad status of " + response.$metadata.httpStatusCode + " from AWS. See server logs at " + errorTime }));
      } else {
        fs.rm(file.path, (err) => {
          if (err) {
            console.error("Error deleting temp file", file.path, "with error:", err);
          }
        });
        res.send(JSON.stringify({ success: true, url: finalUrl }));
      }
    } catch (uploadError) {
      const errorTime = new Date().toISOString();
      console.error(errorTime, "Error uploading to S3:", uploadError);
      res.status(500).send(JSON.stringify({ success: false, message: "Got error uploading file. See server logs at " + errorTime + " Error Details: " + JSON.stringify(uploadError) }));
    }
  });
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

// Close the database connection when the Node.js app ends
process.on('SIGINT', () => {
  db.close((err) => {
    if (err) {
      return console.error('Error closing DB connection', err);
    }
    process.exit(0);
  });
});