"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = require("express");
const uuid_1 = require("uuid");
const config_1 = require("../config");
const router = (0, express_1.Router)();
/** Detect circular parentId references (A→B→A). Returns true if adding parentId to targetId would create a cycle. */
function hasCycle(shortcuts, targetId, parentId) {
    let current = parentId;
    const visited = new Set();
    while (current) {
        if (current === targetId || visited.has(current))
            return true;
        visited.add(current);
        current = shortcuts.find((s) => s.id === current)?.parentId;
    }
    return false;
}
// GET /api/shortcuts
router.get('/', (req, res) => {
    res.json((0, config_1.getGlobalShortcuts)(req.user?.username));
});
// POST /api/shortcuts
router.post('/', (req, res) => {
    const { label, command, parentId } = req.body;
    if (!command?.trim()) {
        res.status(400).json({ error: 'command is required' });
        return;
    }
    const username = req.user?.username;
    const shortcuts = (0, config_1.getGlobalShortcuts)(username);
    if (parentId && !shortcuts.some((s) => s.id === parentId)) {
        res.status(400).json({ error: 'Parent shortcut not found' });
        return;
    }
    const shortcut = {
        id: (0, uuid_1.v4)(),
        label: label?.trim() || command.trim(),
        command: command.trim(),
        ...(parentId ? { parentId } : {}),
    };
    shortcuts.push(shortcut);
    (0, config_1.saveGlobalShortcuts)(shortcuts, username);
    res.status(201).json(shortcut);
});
// PUT /api/shortcuts/:id
router.put('/:id', (req, res) => {
    const { id } = req.params;
    const { label, command } = req.body;
    if (!command?.trim()) {
        res.status(400).json({ error: 'command is required' });
        return;
    }
    const username = req.user?.username;
    const shortcuts = (0, config_1.getGlobalShortcuts)(username);
    const idx = shortcuts.findIndex((s) => s.id === id);
    if (idx < 0) {
        res.status(404).json({ error: 'Not found' });
        return;
    }
    const { parentId } = req.body;
    if (parentId && !shortcuts.some((s) => s.id === parentId)) {
        res.status(400).json({ error: 'Parent shortcut not found' });
        return;
    }
    if (parentId && hasCycle(shortcuts, id, parentId)) {
        res.status(400).json({ error: 'Circular parent reference detected' });
        return;
    }
    shortcuts[idx] = {
        id, label: label?.trim() || command.trim(), command: command.trim(),
        ...(parentId ? { parentId } : parentId === null ? {} : { parentId: shortcuts[idx].parentId }),
    };
    (0, config_1.saveGlobalShortcuts)(shortcuts, username);
    res.json(shortcuts[idx]);
});
// DELETE /api/shortcuts/:id
router.delete('/:id', (req, res) => {
    const { id } = req.params;
    const username = req.user?.username;
    const shortcuts = (0, config_1.getGlobalShortcuts)(username);
    const filtered = shortcuts.filter((s) => s.id !== id);
    if (filtered.length === shortcuts.length) {
        res.status(404).json({ error: 'Not found' });
        return;
    }
    (0, config_1.saveGlobalShortcuts)(filtered, username);
    res.json({ success: true });
});
// ── Project shortcuts (stored in .ccweb/shortcuts.json) ──────────────────────
function resolveProjectFolder(projectId, username, res) {
    const project = (0, config_1.getProject)(projectId);
    if (!project) {
        res.status(404).json({ error: 'Project not found' });
        return null;
    }
    if (!(0, config_1.isAdminUser)(username) && !(0, config_1.isProjectOwner)(project, username) &&
        !project.shares?.some((s) => s.username === username && s.permission === 'edit')) {
        res.status(403).json({ error: 'Access denied' });
        return null;
    }
    return project.folderPath;
}
// GET /api/shortcuts/project/:projectId
router.get('/project/:projectId', (req, res) => {
    const folder = resolveProjectFolder(req.params.projectId, req.user?.username || '', res);
    if (!folder)
        return;
    res.json((0, config_1.readProjectShortcuts)(folder));
});
// POST /api/shortcuts/project/:projectId
router.post('/project/:projectId', (req, res) => {
    const folder = resolveProjectFolder(req.params.projectId, req.user?.username || '', res);
    if (!folder)
        return;
    const { label, command } = req.body;
    if (!command?.trim()) {
        res.status(400).json({ error: 'command is required' });
        return;
    }
    const shortcuts = (0, config_1.readProjectShortcuts)(folder);
    const shortcut = { id: (0, uuid_1.v4)(), label: label?.trim() || command.trim(), command: command.trim() };
    shortcuts.push(shortcut);
    (0, config_1.saveProjectShortcuts)(folder, shortcuts);
    res.status(201).json(shortcut);
});
// PUT /api/shortcuts/project/:projectId/:id
router.put('/project/:projectId/:id', (req, res) => {
    const folder = resolveProjectFolder(req.params.projectId, req.user?.username || '', res);
    if (!folder)
        return;
    const { id } = req.params;
    const { label, command } = req.body;
    if (!command?.trim()) {
        res.status(400).json({ error: 'command is required' });
        return;
    }
    const shortcuts = (0, config_1.readProjectShortcuts)(folder);
    const idx = shortcuts.findIndex((s) => s.id === id);
    if (idx < 0) {
        res.status(404).json({ error: 'Not found' });
        return;
    }
    // Preserve fields not in the edit payload (notably `used` — otherwise the
    // "never-used" blue flag would reset every time the user edits a shortcut).
    shortcuts[idx] = {
        ...shortcuts[idx],
        id,
        label: label?.trim() || command.trim(),
        command: command.trim(),
    };
    (0, config_1.saveProjectShortcuts)(folder, shortcuts);
    res.json(shortcuts[idx]);
});
// PATCH /api/shortcuts/project/:projectId/:id/used  body: { used: boolean }
// Idempotent toggle for the "has ever been clicked" flag. Usually called
// fire-and-forget from the client right after dispatching the shortcut's
// command. Separate from the PUT edit endpoint so users without edit
// permission (view-share) still can't flip it — but any caller who can see
// the project (owner / edit-share) can mark-used.
router.patch('/project/:projectId/:id/used', (req, res) => {
    const folder = resolveProjectFolder(req.params.projectId, req.user?.username || '', res);
    if (!folder)
        return;
    const { id } = req.params;
    const { used } = (req.body ?? {});
    if (typeof used !== 'boolean') {
        res.status(400).json({ error: 'used must be boolean' });
        return;
    }
    const shortcuts = (0, config_1.readProjectShortcuts)(folder);
    const idx = shortcuts.findIndex((s) => s.id === id);
    if (idx < 0) {
        res.status(404).json({ error: 'Not found' });
        return;
    }
    if (shortcuts[idx].used === used) {
        // No-op: skip disk write on the hot path (every prompt click fires PATCH).
        res.json(shortcuts[idx]);
        return;
    }
    shortcuts[idx] = { ...shortcuts[idx], used };
    (0, config_1.saveProjectShortcuts)(folder, shortcuts);
    res.json(shortcuts[idx]);
});
// DELETE /api/shortcuts/project/:projectId/:id
router.delete('/project/:projectId/:id', (req, res) => {
    const folder = resolveProjectFolder(req.params.projectId, req.user?.username || '', res);
    if (!folder)
        return;
    const { id } = req.params;
    const shortcuts = (0, config_1.readProjectShortcuts)(folder);
    const filtered = shortcuts.filter((s) => s.id !== id);
    if (filtered.length === shortcuts.length) {
        res.status(404).json({ error: 'Not found' });
        return;
    }
    (0, config_1.saveProjectShortcuts)(folder, filtered);
    res.json({ success: true });
});
exports.default = router;
//# sourceMappingURL=shortcuts.js.map