/**
 * Skill Tier Service
 *
 * Handles paid skill tier checking and graceful degradation.
 * Resolves which skills an agent can access based on their cloud tier,
 * substituting premium skills with free fallbacks when the user's tier
 * is insufficient.
 *
 * Tier hierarchy: free < pro < enterprise
 *
 * @module services/skill/skill-tier.service
 */
import { CLOUD_CONSTANTS } from '../../constants.js';
import { LoggerService } from '../core/logger.service.js';
/**
 * Numeric weight for each tier, used for comparison.
 * Higher number = higher tier.
 */
const TIER_HIERARCHY = {
    [CLOUD_CONSTANTS.TIERS.FREE]: 0,
    [CLOUD_CONSTANTS.TIERS.PRO]: 1,
    [CLOUD_CONSTANTS.TIERS.ENTERPRISE]: 2,
};
/**
 * Service for checking skill tier requirements and performing graceful degradation.
 *
 * When an agent's assigned skills include premium skills that exceed the user's
 * cloud tier, this service substitutes them with free-tier fallbacks (if available)
 * or removes them entirely, producing a degradation notice for the agent prompt.
 */
export class SkillTierService {
    static instance = null;
    logger;
    constructor() {
        this.logger = LoggerService.getInstance().createComponentLogger('SkillTierService');
    }
    /**
     * Get the singleton instance of SkillTierService.
     *
     * @returns The SkillTierService singleton
     */
    static getInstance() {
        if (!SkillTierService.instance) {
            SkillTierService.instance = new SkillTierService();
        }
        return SkillTierService.instance;
    }
    /**
     * Reset the singleton instance (for testing).
     */
    static resetInstance() {
        SkillTierService.instance = null;
    }
    /**
     * Check whether a user's tier is sufficient for a required tier.
     *
     * @param userTier - The user's current cloud tier
     * @param requiredTier - The minimum tier required
     * @returns true if userTier >= requiredTier in the hierarchy
     */
    isTierSufficient(userTier, requiredTier) {
        const userLevel = TIER_HIERARCHY[userTier] ?? 0;
        const requiredLevel = TIER_HIERARCHY[requiredTier] ?? 0;
        return userLevel >= requiredLevel;
    }
    /**
     * Resolve a set of assigned skills against the user's tier.
     *
     * For each skill:
     * - If no requiredTier or requiredTier <= userTier → included as 'direct'
     * - If requiredTier > userTier and fallbackSkill exists → replaced with fallback as 'degraded'
     * - If requiredTier > userTier and no fallback → excluded and listed in degraded
     *
     * @param assignedSkills - Array of skill tier info objects
     * @param userTier - The user's current cloud tier
     * @returns Resolved skill set with accessible skills and degradation info
     */
    resolveSkills(assignedSkills, userTier) {
        const skills = [];
        const degraded = [];
        for (const skill of assignedSkills) {
            const requiredTier = skill.requiredTier || CLOUD_CONSTANTS.TIERS.FREE;
            if (this.isTierSufficient(userTier, requiredTier)) {
                skills.push({ id: skill.id, source: 'direct' });
            }
            else {
                const degradedEntry = {
                    original: skill.id,
                    fallback: skill.fallbackSkill || null,
                    requiredTier: requiredTier,
                };
                degraded.push(degradedEntry);
                if (skill.fallbackSkill) {
                    skills.push({ id: skill.fallbackSkill, source: 'degraded' });
                }
            }
        }
        if (degraded.length > 0) {
            this.logger.info('Skills degraded due to insufficient tier', {
                userTier,
                degradedCount: degraded.length,
                degraded: degraded.map(d => ({
                    original: d.original,
                    fallback: d.fallback,
                    requiredTier: d.requiredTier,
                })),
            });
        }
        return { skills, degraded };
    }
    /**
     * Build a human-readable degradation notice for injection into agent prompts.
     *
     * @param degraded - Array of degraded skills from resolveSkills()
     * @param userTier - The user's current tier (for display)
     * @returns Markdown-formatted notice string, or empty string if no degradations
     */
    buildDegradationNotice(degraded, userTier) {
        if (degraded.length === 0) {
            return '';
        }
        const lines = [
            '## Premium Skills Notice',
            '',
            `Your team template includes the following premium skills but current account is **${userTier}** tier:`,
            '',
        ];
        for (const d of degraded) {
            if (d.fallback) {
                lines.push(`- **${d.original}** → downgraded to \`${d.fallback}\` (requires ${d.requiredTier})`);
            }
            else {
                lines.push(`- **${d.original}** → not available (requires ${d.requiredTier})`);
            }
        }
        lines.push('');
        lines.push('Upgrade at https://crewlyai.com/pricing');
        return lines.join('\n');
    }
}
/**
 * Get the singleton SkillTierService instance.
 *
 * @returns The SkillTierService singleton
 */
export function getSkillTierService() {
    return SkillTierService.getInstance();
}
/**
 * Reset the SkillTierService singleton (for testing).
 */
export function resetSkillTierService() {
    SkillTierService.resetInstance();
}
//# sourceMappingURL=skill-tier.service.js.map