/**
 * In-Memory SupervisorPolicy Repository
 *
 * Test-friendly adapter for {@link ISupervisorPolicyRepository}. Enforces
 * the unique-(scopeType, scopeId, featureId) constraint and the
 * feature-then-scope fallback documented in research decision 7.
 */
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { injectable } from 'tsyringe';
function scopeKey(scopeType, scopeId, featureId) {
    return `${scopeType}::${scopeId ?? ''}::${featureId ?? ''}`;
}
function scopeMatches(row, scopeType, scopeId) {
    return row.scopeType === scopeType && (row.scopeId ?? undefined) === (scopeId ?? undefined);
}
let InMemorySupervisorPolicyRepository = class InMemorySupervisorPolicyRepository {
    policies = new Map();
    async create(policy) {
        if (this.policies.has(policy.id)) {
            throw new Error(`SupervisorPolicy with id "${policy.id}" already exists`);
        }
        const key = scopeKey(policy.scopeType, policy.scopeId, policy.featureId ?? undefined);
        for (const existing of this.policies.values()) {
            if (scopeKey(existing.scopeType, existing.scopeId, existing.featureId ?? undefined) === key) {
                throw new Error(`SupervisorPolicy already exists for scopeType=${policy.scopeType}, scopeId=${policy.scopeId ?? '(null)'}, featureId=${policy.featureId ?? '(null)'}`);
            }
        }
        this.policies.set(policy.id, { ...policy });
    }
    async update(policy) {
        if (!this.policies.has(policy.id)) {
            throw new Error(`SupervisorPolicy with id "${policy.id}" not found`);
        }
        this.policies.set(policy.id, { ...policy });
    }
    async delete(id) {
        this.policies.delete(id);
    }
    async findById(id) {
        const row = this.policies.get(id);
        return row ? { ...row } : null;
    }
    async findByScope(scopeType, scopeId) {
        for (const row of this.policies.values()) {
            if (scopeMatches(row, scopeType, scopeId) &&
                (row.featureId === undefined || row.featureId === null)) {
                return { ...row };
            }
        }
        return null;
    }
    async findByScopeAndFeature(scopeType, scopeId, featureId) {
        for (const row of this.policies.values()) {
            if (scopeMatches(row, scopeType, scopeId) && row.featureId === featureId) {
                return { ...row };
            }
        }
        return null;
    }
    async findPolicyForScope(scopeType, scopeId, featureId) {
        if (featureId !== undefined) {
            const featureRow = await this.findByScopeAndFeature(scopeType, scopeId, featureId);
            if (featureRow)
                return featureRow;
        }
        return this.findByScope(scopeType, scopeId);
    }
    async listByScope(scopeType, scopeId) {
        const result = [];
        for (const row of this.policies.values()) {
            if (scopeMatches(row, scopeType, scopeId))
                result.push({ ...row });
        }
        return result;
    }
    async listAll() {
        return [...this.policies.values()]
            .map((row) => ({ ...row }))
            .sort((a, b) => {
            if (a.scopeType !== b.scopeType)
                return a.scopeType.localeCompare(b.scopeType);
            const idCompare = (a.scopeId ?? '').localeCompare(b.scopeId ?? '');
            if (idCompare !== 0)
                return idCompare;
            return (a.featureId ?? '').localeCompare(b.featureId ?? '');
        });
    }
};
InMemorySupervisorPolicyRepository = __decorate([
    injectable()
], InMemorySupervisorPolicyRepository);
export { InMemorySupervisorPolicyRepository };
