import { Router, type Request, type Response } from 'express';
import { authMiddleware } from '../middleware/auth';
import { requirePaid, requireAdmin, requireBody } from '../middleware/tierGates';
import { DatabaseService } from '../services/DatabaseService';
import { NodeLabelService } from '../services/NodeLabelService';
import { parseIntParam } from '../utils/parseIntParam';

export const nodeLabelsRouter = Router();

nodeLabelsRouter.use(authMiddleware);

nodeLabelsRouter.get('/', (req: Request, res: Response): void => {
    if (!requirePaid(req, res)) return;
    try {
        const map = NodeLabelService.getInstance().listAll();
        res.json(map);
    } catch (error) {
        console.error('[NodeLabels] List error:', error);
        res.status(500).json({ error: 'Failed to list node labels' });
    }
});

nodeLabelsRouter.get('/all', (req: Request, res: Response): void => {
    if (!requirePaid(req, res)) return;
    try {
        const labels = NodeLabelService.getInstance().listDistinct();
        res.json({ labels });
    } catch (error) {
        console.error('[NodeLabels] List distinct error:', error);
        res.status(500).json({ error: 'Failed to list distinct labels' });
    }
});

nodeLabelsRouter.get('/:nodeId', (req: Request, res: Response): void => {
    if (!requirePaid(req, res)) return;
    const nodeId = parseIntParam(req, res, 'nodeId');
    if (nodeId === null) return;
    try {
        const node = DatabaseService.getInstance().getNode(nodeId);
        if (!node) {
            res.status(404).json({ error: 'Node not found' });
            return;
        }
        const labels = NodeLabelService.getInstance().listForNode(nodeId);
        res.json({ nodeId, labels });
    } catch (error) {
        console.error('[NodeLabels] Get-for-node error:', error);
        res.status(500).json({ error: 'Failed to fetch node labels' });
    }
});

nodeLabelsRouter.post('/:nodeId', (req: Request, res: Response): void => {
    if (!requirePaid(req, res)) return;
    if (!requireAdmin(req, res)) return;
    if (!requireBody(req, res)) return;
    const nodeId = parseIntParam(req, res, 'nodeId');
    if (nodeId === null) return;
    const label = typeof req.body.label === 'string' ? req.body.label : '';
    try {
        const node = DatabaseService.getInstance().getNode(nodeId);
        if (!node) {
            res.status(404).json({ error: 'Node not found' });
            return;
        }
        const result = NodeLabelService.getInstance().addLabel(nodeId, label);
        if (!result.ok) {
            res.status(400).json(result.error);
            return;
        }
        res.status(201).json({ nodeId, label: result.label });
    } catch (error) {
        console.error('[NodeLabels] Add error:', error);
        res.status(500).json({ error: 'Failed to add label' });
    }
});

nodeLabelsRouter.delete('/:nodeId/:label', (req: Request, res: Response): void => {
    if (!requirePaid(req, res)) return;
    if (!requireAdmin(req, res)) return;
    const nodeId = parseIntParam(req, res, 'nodeId');
    if (nodeId === null) return;
    const labelParam = req.params.label;
    const label = typeof labelParam === 'string' ? labelParam : '';
    if (!label) {
        res.status(400).json({ error: 'label is required' });
        return;
    }
    try {
        const removed = NodeLabelService.getInstance().removeLabel(nodeId, label);
        if (!removed) {
            res.status(404).json({ error: 'Label assignment not found' });
            return;
        }
        res.status(204).end();
    } catch (error) {
        console.error('[NodeLabels] Remove error:', error);
        res.status(500).json({ error: 'Failed to remove label' });
    }
});
