"use strict";
/**
 * Variant Routes - CLIProxy variant management (custom profiles)
 *
 * Uses variant-service.ts for proper port allocation and cleanup.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseTarget = void 0;
const express_1 = require("express");
const reserved_names_1 = require("../../config/reserved-names");
const target_metadata_1 = require("../../targets/target-metadata");
const route_helpers_1 = require("./route-helpers");
const variant_service_1 = require("../../cliproxy/services/variant-service");
const composite_validator_1 = require("../../cliproxy/config/composite-validator");
const router = (0, express_1.Router)();
/**
 * GET /api/cliproxy - List cliproxy variants
 * Uses variant-service for consistent behavior with CLI
 */
router.get('/', (_req, res) => {
    const variants = (0, variant_service_1.listVariants)();
    const variantList = Object.entries(variants).map(([name, variant]) => ({
        name,
        provider: variant.provider,
        settings: variant.settings,
        account: variant.account || 'default',
        port: variant.port, // Include port for port isolation
        model: variant.model,
        target: variant.target || 'claude',
        type: variant.type,
        default_tier: variant.default_tier,
        tiers: variant.tiers,
    }));
    res.json({ variants: variantList });
});
/**
 * POST /api/cliproxy - Create cliproxy variant
 * Uses variant-service for proper port allocation
 */
router.post('/', (req, res) => {
    const { name, provider, model, account, type, default_tier, tiers } = req.body;
    const parsedTarget = (0, route_helpers_1.parseTarget)(req.body.target);
    if (req.body.target !== undefined && parsedTarget === null) {
        res.status(400).json({ error: `Invalid target. Expected: ${(0, target_metadata_1.getPersistedTargetChoices)()}` });
        return;
    }
    if (!name) {
        res.status(400).json({ error: 'Missing required field: name' });
        return;
    }
    // Validate profile name
    const validationError = (0, variant_service_1.validateProfileName)(name);
    if (validationError) {
        res.status(400).json({ error: validationError });
        return;
    }
    // Reject reserved names (extra safety check)
    if ((0, reserved_names_1.isReservedName)(name)) {
        res.status(400).json({
            error: `Cannot use reserved name '${name}' as variant name`,
            reserved: reserved_names_1.RESERVED_PROFILE_NAMES,
        });
        return;
    }
    // Handle composite variant creation
    if (type === 'composite') {
        if (!default_tier || !tiers) {
            res.status(400).json({ error: 'Missing required fields: default_tier, tiers' });
            return;
        }
        // Validate tiers shape, providers, and default_tier (all tiers required for create)
        const tierError = (0, composite_validator_1.validateCompositeTiers)(tiers, {
            defaultTier: default_tier,
            requireAllTiers: true,
        });
        if (tierError) {
            res.status(400).json({ error: tierError });
            return;
        }
        let result;
        try {
            result = (0, variant_service_1.createCompositeVariant)({
                name,
                defaultTier: default_tier,
                target: parsedTarget || 'claude',
                tiers,
            });
        }
        catch (error) {
            res.status(400).json({ error: error.message });
            return;
        }
        if (!result.success) {
            res.status(409).json({ error: result.error });
            return;
        }
        res.status(201).json({
            name,
            type: 'composite',
            default_tier,
            tiers,
            settings: result.settingsPath,
            port: result.variant?.port,
            target: result.variant?.target || 'claude',
        });
        return;
    }
    // Handle single provider variant creation
    if (!provider) {
        res.status(400).json({ error: 'Missing required field: provider' });
        return;
    }
    // Require model for variant creation (prevents empty model causing issues)
    if (!model || !model.trim()) {
        res.status(400).json({ error: 'Missing required field: model' });
        return;
    }
    // Use variant-service for proper port allocation
    const result = (0, variant_service_1.createVariant)(name, provider, model, account, parsedTarget || 'claude');
    if (!result.success) {
        res.status(409).json({ error: result.error });
        return;
    }
    res.status(201).json({
        name,
        provider,
        settings: result.settingsPath,
        account: account || 'default',
        port: result.variant?.port,
        model: result.variant?.model,
        target: result.variant?.target || 'claude',
    });
});
/**
 * PUT /api/cliproxy/:name - Update cliproxy variant
 * Uses variant-service for consistent behavior with CLI
 *
 * TODO: Add file-based locking (e.g., proper-lockfile) to prevent concurrent modification
 * Current behavior: last-write-wins if two requests modify same variant simultaneously
 */
router.put('/:name', (req, res) => {
    try {
        const { name } = req.params;
        const { provider, account, model, default_tier, tiers } = req.body;
        const parsedTarget = (0, route_helpers_1.parseTarget)(req.body.target);
        if (req.body.target !== undefined && parsedTarget === null) {
            res.status(400).json({ error: `Invalid target. Expected: ${(0, target_metadata_1.getPersistedTargetChoices)()}` });
            return;
        }
        // Check if variant is composite - use updateCompositeVariant if so
        const variants = (0, variant_service_1.listVariants)();
        const existing = variants[name];
        if (!existing) {
            res.status(404).json({ error: `Variant '${name}' not found` });
            return;
        }
        if (existing.type === 'composite') {
            if (!default_tier && !tiers && req.body.target === undefined) {
                res.status(400).json({ error: 'Must provide at least default_tier, tiers, or target' });
                return;
            }
            // Validate tiers shape, providers, and default_tier if provided
            if (tiers) {
                const tierError = (0, composite_validator_1.validateCompositeTiers)(tiers, {
                    defaultTier: default_tier,
                });
                if (tierError) {
                    res.status(400).json({ error: tierError });
                    return;
                }
            }
            else {
                const defaultTierError = (0, composite_validator_1.validateCompositeDefaultTier)(default_tier);
                if (defaultTierError) {
                    res.status(400).json({
                        error: defaultTierError,
                    });
                    return;
                }
            }
            const result = (0, variant_service_1.updateCompositeVariant)(name, {
                defaultTier: default_tier,
                tiers,
                target: req.body.target !== undefined && parsedTarget ? parsedTarget : undefined,
            });
            if (!result.success) {
                const status = result.error?.includes('not found') ? 404 : 400;
                res.status(status).json({
                    error: result.error,
                });
                return;
            }
            const persisted = result.variant;
            res.json({
                name,
                type: 'composite',
                default_tier: persisted?.default_tier,
                tiers: persisted?.tiers,
                settings: persisted?.settings,
                port: persisted?.port,
                target: persisted?.target || 'claude',
                updated: true,
            });
            return;
        }
        // Use variant-service for proper update handling (single provider)
        const result = (0, variant_service_1.updateVariant)(name, {
            provider,
            account,
            model,
            target: req.body.target !== undefined && parsedTarget ? parsedTarget : undefined,
        });
        if (!result.success) {
            const status = result.error?.includes('not found') ? 404 : 400;
            res.status(status).json({ error: result.error });
            return;
        }
        res.json({
            name,
            provider: result.variant?.provider,
            account: result.variant?.account || 'default',
            settings: result.variant?.settings,
            port: result.variant?.port,
            target: result.variant?.target || 'claude',
            updated: true,
        });
    }
    catch (error) {
        res.status(500).json({ error: error.message });
    }
});
/**
 * DELETE /api/cliproxy/:name - Delete cliproxy variant
 * Uses variant-service for proper port-specific file cleanup
 */
router.delete('/:name', (req, res) => {
    try {
        const { name } = req.params;
        // Use variant-service for proper cleanup (settings, config, session files)
        const result = (0, variant_service_1.removeVariant)(name);
        if (!result.success) {
            res.status(404).json({ error: result.error });
            return;
        }
        res.json({ name, deleted: true, port: result.variant?.port });
    }
    catch (error) {
        res.status(500).json({ error: error.message });
    }
});
exports.default = router;
var route_helpers_2 = require("./route-helpers");
Object.defineProperty(exports, "parseTarget", { enumerable: true, get: function () { return route_helpers_2.parseTarget; } });
//# sourceMappingURL=variant-routes.js.map