// src/routes/content.js
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const express = require('express');
const db = require('../db');
const requireAdmin = require('../middleware/requireAdmin');
const { logAudit } = require('../middleware/audit');

const router = express.Router();

// ---- helpers -------------------------------------------------------------
function makeCrud({ table, fields, publicWhere = 'published = 1', label }) {
  const cols = fields.join(', ');
  const placeholders = fields.map(() => '?').join(', ');

  return {
    listPublic(req, res) {
      const rows = db.prepare(`SELECT * FROM ${table} WHERE ${publicWhere} ORDER BY created_at DESC`).all();
      res.json(rows);
    },
    listAdmin(req, res) {
      const rows = db.prepare(`SELECT * FROM ${table} ORDER BY created_at DESC`).all();
      res.json(rows);
    },
    create(req, res) {
      const values = fields.map((f) => (req.body?.[f] ?? null));
      const info = db.prepare(`INSERT INTO ${table} (${cols}) VALUES (${placeholders})`).run(...values);
      const row = db.prepare(`SELECT * FROM ${table} WHERE id = ?`).get(info.lastInsertRowid);
      logAudit(req, 'create', table, row.id, `${label || table}: "${row.title || row.name || ''}"`);
      res.status(201).json(row);
    },
    update(req, res) {
      const existing = db.prepare(`SELECT * FROM ${table} WHERE id = ?`).get(req.params.id);
      const sets = fields.map((f) => `${f} = ?`).join(', ');
      const values = fields.map((f) => (req.body?.[f] ?? null));
      db.prepare(`UPDATE ${table} SET ${sets} WHERE id = ?`).run(...values, req.params.id);
      const row = db.prepare(`SELECT * FROM ${table} WHERE id = ?`).get(req.params.id);
      if (existing && fields.includes('published') && String(existing.published) !== String(row.published)) {
        logAudit(req, row.published == 1 ? 'publish' : 'unpublish', table, row.id, `${label || table}: "${row.title || ''}"`);
      } else {
        logAudit(req, 'update', table, row.id, `${label || table}: "${row.title || ''}"`);
      }
      res.json(row);
    },
    remove(req, res) {
      const existing = db.prepare(`SELECT * FROM ${table} WHERE id = ?`).get(req.params.id);
      db.prepare(`DELETE FROM ${table} WHERE id = ?`).run(req.params.id);
      logAudit(req, 'delete', table, req.params.id, existing ? `${label || table}: "${existing.title || ''}"` : null);
      res.json({ ok: true });
    }
  };
}

const stories = makeCrud({ table: 'stories', fields: ['category', 'tone', 'title', 'excerpt', 'body', 'published'], label: 'Project' });
const insights = makeCrud({ table: 'insights', fields: ['tab', 'tone', 'badge', 'title', 'excerpt', 'link', 'published'], label: 'Insight post' });
const press = makeCrud({ table: 'press', fields: ['tone', 'badge', 'title', 'excerpt', 'link', 'published'], label: 'Press item' });
const events = makeCrud({ table: 'events', fields: ['title', 'description', 'event_date', 'published'], publicWhere: "published = 1 AND date(event_date) >= date('now')", label: 'Event' });
const media = makeCrud({ table: 'media', fields: ['media_type', 'category', 'title', 'caption', 'url', 'thumbnail_url', 'published'], label: 'Media item' });

// ---- stories ----
router.get('/stories', stories.listPublic);
router.get('/admin/stories', requireAdmin, stories.listAdmin);
router.post('/admin/stories', requireAdmin, stories.create);
router.put('/admin/stories/:id', requireAdmin, stories.update);
router.delete('/admin/stories/:id', requireAdmin, stories.remove);

// ---- insights (posts) ----
router.get('/insights', insights.listPublic);
router.get('/admin/insights', requireAdmin, insights.listAdmin);
router.post('/admin/insights', requireAdmin, insights.create);
router.put('/admin/insights/:id', requireAdmin, insights.update);
router.delete('/admin/insights/:id', requireAdmin, insights.remove);

// ---- press ----
router.get('/press', press.listPublic);
router.get('/admin/press', requireAdmin, press.listAdmin);
router.post('/admin/press', requireAdmin, press.create);
router.put('/admin/press/:id', requireAdmin, press.update);
router.delete('/admin/press/:id', requireAdmin, press.remove);

// ---- events ----
router.get('/events', events.listPublic);
router.get('/admin/events', requireAdmin, events.listAdmin);
router.post('/admin/events', requireAdmin, events.create);
router.put('/admin/events/:id', requireAdmin, events.update);
router.delete('/admin/events/:id', requireAdmin, events.remove);

// ---- media (photo / video gallery, feeds the public Media page) ----
router.get('/media', (req, res) => {
  const category = typeof req.query.category === 'string' ? req.query.category : null;
  const rows = category
    ? db.prepare(`SELECT * FROM media WHERE published = 1 AND category = ? ORDER BY created_at DESC`).all(category)
    : db.prepare(`SELECT * FROM media WHERE published = 1 ORDER BY created_at DESC`).all();
  res.json(rows);
});
router.get('/admin/media', requireAdmin, media.listAdmin);
router.post('/admin/media', requireAdmin, media.create);
router.put('/admin/media/:id', requireAdmin, media.update);
router.delete('/admin/media/:id', requireAdmin, media.remove);

// ---- media file upload ----
// Accepts a base64 data URL and writes it to /public/assets/uploads, so no
// extra npm dependency (e.g. multer) is required on shared hosting. Images
// only; kept deliberately small and validated to limit abuse.
const UPLOAD_DIR = path.join(__dirname, '..', '..', '..', 'public', 'assets', 'uploads');
const ALLOWED_MIME = { 'image/jpeg': 'jpg', 'image/png': 'png', 'image/webp': 'webp', 'image/gif': 'gif' };
const MAX_UPLOAD_BYTES = 4 * 1024 * 1024; // 4MB decoded

router.post('/admin/media/upload', requireAdmin, (req, res) => {
  try {
    const { dataUrl, filename } = req.body || {};
    if (!dataUrl || typeof dataUrl !== 'string') return res.status(400).json({ error: 'No file data received.' });
    const match = dataUrl.match(/^data:([\w/+.-]+);base64,(.+)$/);
    if (!match) return res.status(400).json({ error: 'File must be a base64 data URL.' });
    const mime = match[1].toLowerCase();
    const ext = ALLOWED_MIME[mime];
    if (!ext) return res.status(400).json({ error: 'Only JPG, PNG, WEBP or GIF images are allowed.' });

    const buffer = Buffer.from(match[2], 'base64');
    if (buffer.length > MAX_UPLOAD_BYTES) {
      return res.status(413).json({ error: 'File is too large. Please keep uploads under 4MB.' });
    }

    if (!fs.existsSync(UPLOAD_DIR)) fs.mkdirSync(UPLOAD_DIR, { recursive: true });
    const safeName = `${Date.now()}-${crypto.randomBytes(6).toString('hex')}.${ext}`;
    fs.writeFileSync(path.join(UPLOAD_DIR, safeName), buffer);

    logAudit(req, 'create', 'media', null, `Uploaded file ${safeName} (${(buffer.length / 1024).toFixed(0)}KB) — original name: ${String(filename || '').slice(0, 120)}`);
    res.status(201).json({ url: `/assets/uploads/${safeName}` });
  } catch (e) {
    console.error('[media upload] failed:', e.message);
    res.status(500).json({ error: 'Upload failed on the server.' });
  }
});

module.exports = router;
