// ============================================================
// DOCUMENTS ROUTES — S3-backed document upload & management
// ============================================================

var express = require('express');
var router = express.Router();
var multer = require('multer');
var crypto = require('crypto');
var db = require('../db/database');
var { authMiddleware } = require('../middleware/auth');
var logger = require('../utils/logger');

router.use(authMiddleware);

var upload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: 10 * 1024 * 1024 } // 10 MB
});

var ALLOWED_TYPES = [
  'application/pdf',
  'image/jpeg', 'image/png', 'image/gif',
  'application/msword',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'text/plain', 'text/csv'
];

// Lazy-load S3 client
var _s3Client = null;
function getS3Client() {
  if (_s3Client) return _s3Client;
  try {
    var { S3Client } = require('@aws-sdk/client-s3');
    var region = process.env.S3_REGION || process.env.AWS_BEDROCK_REGION || 'us-east-1';
    var config = { region: region };

    // Custom endpoint for S3-compatible providers (Backblaze B2, MinIO, etc.)
    if (process.env.S3_ENDPOINT) {
      config.endpoint = process.env.S3_ENDPOINT;
      config.forcePathStyle = process.env.S3_FORCE_PATH_STYLE === 'true'; // Required for MinIO
    }

    // Credentials: use S3-specific keys first, fall back to AWS keys
    var accessKey = process.env.S3_ACCESS_KEY_ID || process.env.AWS_ACCESS_KEY_ID;
    var secretKey = process.env.S3_SECRET_ACCESS_KEY || process.env.AWS_SECRET_ACCESS_KEY;
    if (accessKey && secretKey) {
      config.credentials = {
        accessKeyId: accessKey,
        secretAccessKey: secretKey
      };
    }

    _s3Client = new S3Client(config);
    return _s3Client;
  } catch (e) {
    return null;
  }
}

function isS3Configured() {
  return !!process.env.S3_BUCKET && !!getS3Client();
}

// ── GET list user documents ────────────────────────────────────────────
router.get('/documents', async function(req, res) {
  try {
    if (!isS3Configured()) return res.json({ success: true, documents: [], s3_configured: false });
    var rows = await db.all(
      'SELECT id, filename, mime_type, size_bytes, description, created_at FROM user_documents WHERE user_id = $1 ORDER BY created_at DESC',
      [req.user.id]
    );
    res.json({ success: true, documents: rows, s3_configured: true });
  } catch (e) { logger.error('GET /documents', e.message); res.status(500).json({ error: 'Could not list documents' }); }
});

// ── POST upload document ───────────────────────────────────────────────
router.post('/documents/upload', upload.single('file'), async function(req, res) {
  try {
    if (!isS3Configured()) return res.status(400).json({ error: 'S3 not configured. Set S3_BUCKET and S3_REGION in .env' });
    if (!req.file) return res.status(400).json({ error: 'No file uploaded' });
    if (!ALLOWED_TYPES.includes(req.file.mimetype)) {
      return res.status(400).json({ error: 'File type not allowed. Supported: PDF, images, Word docs, text, CSV' });
    }
    // Magic-byte verification — browser-reported MIME can be spoofed.
    var fileType = require('../utils/fileType');
    if (!fileType.matches(req.file.mimetype, req.file.buffer)) {
      return res.status(400).json({ error: 'File contents do not match the declared type.' });
    }

    var { PutObjectCommand } = require('@aws-sdk/client-s3');
    var prefix = process.env.S3_PREFIX || 'documents/';
    var uuid = crypto.randomUUID();
    var s3Key = prefix + req.user.id + '/' + uuid + '/' + req.file.originalname;

    await getS3Client().send(new PutObjectCommand({
      Bucket: process.env.S3_BUCKET,
      Key: s3Key,
      Body: req.file.buffer,
      ContentType: req.file.mimetype,
      ServerSideEncryption: 'AES256'
    }));

    var result = await db.run(
      'INSERT INTO user_documents (user_id, s3_key, filename, mime_type, size_bytes, description) VALUES ($1,$2,$3,$4,$5,$6)',
      [req.user.id, s3Key, req.file.originalname, req.file.mimetype, req.file.size, req.body.description || '']
    );

    res.json({ success: true, id: result.lastInsertRowid, filename: req.file.originalname });
    logger.audit(req.user.id, 'document_upload', 'Uploaded document id:' + result.lastInsertRowid, req, { category: 'documents' });
  } catch (e) { logger.error('POST /documents/upload', e.message); res.status(500).json({ error: 'Upload failed' }); }
});

// ── GET download document (presigned URL) ──────────────────────────────
router.get('/documents/:id/download', async function(req, res) {
  try {
    if (!isS3Configured()) return res.status(400).json({ error: 'S3 not configured' });
    var doc = await db.get(
      'SELECT * FROM user_documents WHERE id = $1 AND user_id = $2',
      [req.params.id, req.user.id]
    );
    if (!doc) return res.status(404).json({ error: 'Document not found' });

    var { GetObjectCommand } = require('@aws-sdk/client-s3');
    var { getSignedUrl } = require('@aws-sdk/s3-request-presigner');

    var command = new GetObjectCommand({
      Bucket: process.env.S3_BUCKET,
      Key: doc.s3_key,
      ResponseContentDisposition: 'attachment; filename="' + doc.filename + '"'
    });
    var url = await getSignedUrl(getS3Client(), command, { expiresIn: 300 }); // 5 min

    res.json({ success: true, url: url });
    logger.audit(req.user.id, 'document_download', 'Downloaded document ' + req.params.id, req, { category: 'documents' });
  } catch (e) { logger.error('GET /documents/:id/download', e.message); res.status(500).json({ error: 'Download failed' }); }
});

// ── DELETE document ────────────────────────────────────────────────────
router.delete('/documents/:id', async function(req, res) {
  try {
    if (!isS3Configured()) return res.status(400).json({ error: 'S3 not configured' });
    var doc = await db.get(
      'SELECT * FROM user_documents WHERE id = $1 AND user_id = $2',
      [req.params.id, req.user.id]
    );
    if (!doc) return res.status(404).json({ error: 'Document not found' });

    try {
      var { DeleteObjectCommand } = require('@aws-sdk/client-s3');
      await getS3Client().send(new DeleteObjectCommand({
        Bucket: process.env.S3_BUCKET,
        Key: doc.s3_key
      }));
    } catch (s3err) {
      logger.warn('S3 delete failed (continuing with DB delete):', s3err.message);
    }

    await db.run('DELETE FROM user_documents WHERE id = $1 AND user_id = $2', [req.params.id, req.user.id]);
    res.json({ success: true });
    logger.audit(req.user.id, 'document_delete', 'Deleted document ' + req.params.id, req, { category: 'documents' });
  } catch (e) { logger.error('DELETE /documents/:id', e.message); res.status(500).json({ error: 'Delete failed' }); }
});

module.exports = router;
