const express = require('express');
const router = express.Router();
const { v4: uuidv4 } = require('uuid');
const { db } = require('../db/database');
const { PLATFORM_ROLES } = require('../middleware/auth');
// Phase 2.2c: workspace-aware access. Mirrors devices.js / content.js.
const { accessContext } = require('../lib/tenancy');

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

// Per-workspace folder cap. The route has no rate limit (multer doesn't go
// through the global API limiter chain), so without a count cap a workspace
// could insert millions of rows. 100 is generous for a real org hierarchy.
const MAX_FOLDERS_PER_WORKSPACE = 100;

// Resolve a folder and the caller's access to its workspace. Returns:
//   { row, ctx }              - access granted; ctx.workspaceRole / ctx.actingAs available
//   { row: { id: null } }     - root (no folder id supplied) - always accessible
//   null                      - folder not found or no access
//
// Platform-template folders (workspace_id IS NULL) are readable by anyone.
// Writable only by platform_admin (same shape as content.js).
function accessibleFolder(req, folderId, requireWrite = false) {
  if (!folderId) return { row: { id: null }, ctx: null };
  if (!UUID_RE.test(folderId)) return null;
  const row = db.prepare('SELECT * FROM content_folders WHERE id = ?').get(folderId);
  if (!row) return null;

  // Platform-template path
  if (!row.workspace_id) {
    if (requireWrite && !PLATFORM_ROLES.includes(req.user.role)) return null;
    return { row, ctx: null };
  }

  const ws = db.prepare('SELECT * FROM workspaces WHERE id = ?').get(row.workspace_id);
  const ctx = ws && accessContext(req.user.id, req.user.role, ws);
  if (!ctx) return null;
  if (requireWrite && !ctx.actingAs && ctx.workspaceRole === 'workspace_viewer') return null;
  return { row, ctx };
}

// List folders accessible to the caller in their current workspace.
// Includes platform-template folders (workspace_id IS NULL) for everyone.
router.get('/', (req, res) => {
  if (!req.workspaceId) return res.json([]);
  const rows = db.prepare(
    'SELECT * FROM content_folders WHERE (workspace_id = ? OR workspace_id IS NULL) ORDER BY name COLLATE NOCASE'
  ).all(req.workspaceId);
  res.json(rows);
});

// Create a folder in the caller's current workspace.
router.post('/', (req, res) => {
  if (!req.workspaceId) return res.status(403).json({ error: 'No workspace context. Switch to a workspace before creating folders.' });
  const name = (req.body.name || '').trim();
  if (!name) return res.status(400).json({ error: 'name is required' });
  if (name.length > 100) return res.status(400).json({ error: 'name too long' });

  // Per-workspace cap. Platform_admin exempt (cross-workspace admin tooling).
  if (!PLATFORM_ROLES.includes(req.user.role)) {
    const { count } = db.prepare('SELECT COUNT(*) AS count FROM content_folders WHERE workspace_id = ?').get(req.workspaceId);
    if (count >= MAX_FOLDERS_PER_WORKSPACE) {
      return res.status(429).json({
        error: `Folder limit reached (${MAX_FOLDERS_PER_WORKSPACE}). Delete unused folders before creating more.`
      });
    }
  }

  const parentId = req.body.parent_id || null;
  if (parentId) {
    const parent = accessibleFolder(req, parentId, true);
    if (!parent || parent.row.id === null) return res.status(400).json({ error: 'Invalid parent_id' });
    // Parent must be in the same workspace as the new folder.
    if (parent.row.workspace_id !== req.workspaceId) {
      return res.status(400).json({ error: 'Parent folder is in a different workspace' });
    }
  }

  const id = uuidv4();
  db.prepare(
    'INSERT INTO content_folders (id, user_id, workspace_id, parent_id, name) VALUES (?, ?, ?, ?, ?)'
  ).run(id, req.user.id, req.workspaceId, parentId, name);

  res.status(201).json(db.prepare('SELECT * FROM content_folders WHERE id = ?').get(id));
});

// Rename / move a folder.
router.put('/:id', (req, res) => {
  const access = accessibleFolder(req, req.params.id, true);
  if (!access || access.row.id === null) return res.status(404).json({ error: 'Folder not found' });
  const folder = access.row;

  const updates = [];
  const values = [];

  if (req.body.name !== undefined) {
    const name = String(req.body.name).trim();
    if (!name) return res.status(400).json({ error: 'name cannot be empty' });
    if (name.length > 100) return res.status(400).json({ error: 'name too long' });
    updates.push('name = ?');
    values.push(name);
  }

  if (req.body.parent_id !== undefined) {
    const newParent = req.body.parent_id || null;
    if (newParent === folder.id) return res.status(400).json({ error: 'Folder cannot be its own parent' });
    if (newParent) {
      const parent = accessibleFolder(req, newParent, true);
      if (!parent || parent.row.id === null) return res.status(400).json({ error: 'Invalid parent_id' });
      // New parent must be in the same workspace as this folder.
      if (parent.row.workspace_id !== folder.workspace_id) {
        return res.status(400).json({ error: 'Cannot move folder to a parent in another workspace' });
      }
      // Reject cycles: walk up from the new parent and ensure we never hit this folder.
      let cursor = parent.row;
      const seen = new Set([folder.id]);
      while (cursor && cursor.parent_id) {
        if (seen.has(cursor.parent_id)) {
          return res.status(400).json({ error: 'Move would create a cycle' });
        }
        seen.add(cursor.parent_id);
        cursor = db.prepare('SELECT * FROM content_folders WHERE id = ?').get(cursor.parent_id);
      }
    }
    updates.push('parent_id = ?');
    values.push(newParent);
  }

  if (updates.length === 0) return res.json(folder);

  values.push(folder.id);
  db.prepare(`UPDATE content_folders SET ${updates.join(', ')} WHERE id = ?`).run(...values);
  res.json(db.prepare('SELECT * FROM content_folders WHERE id = ?').get(folder.id));
});

// Delete a folder. Content inside it falls back to root via ON DELETE SET NULL.
// Subfolders cascade-delete; if the user wants to keep them they should move them first.
router.delete('/:id', (req, res) => {
  const access = accessibleFolder(req, req.params.id, true);
  if (!access || access.row.id === null) return res.status(404).json({ error: 'Folder not found' });

  db.prepare('DELETE FROM content_folders WHERE id = ?').run(access.row.id);
  res.json({ success: true });
});

module.exports = router;
