"use strict";
// src/test_design_registry_search.ts
// v1.15.0 — Phase A3 regression. Tests:
//   1. search() returns ranked matches by id/title/archetype.
//   2. search() falls into body text when meta misses.
//   3. search() filters narrow before scoring.
//   4. findByArchetype() filter helper.
//   5. findByTokenColor() finds profiles near a target color.
//   6. diff() returns structured token-level deltas.
//   7. diff() handles missing profile gracefully.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const DesignMdRegistry_1 = require("./design/DesignMdRegistry");
function assert(cond, msg) {
    if (!cond)
        throw new Error(`assertion failed: ${msg}`);
}
function mkTmpRoot() {
    return fs.mkdtempSync(path.join(os.tmpdir(), 'design-search-'));
}
function rmTmp(dir) {
    try {
        fs.rmSync(dir, { recursive: true, force: true });
    }
    catch { /* */ }
}
function seedProfile(root, opts) {
    const dir = path.join(root, 'design', 'profiles', opts.id);
    fs.mkdirSync(dir, { recursive: true });
    fs.writeFileSync(path.join(dir, 'DESIGN.md'), opts.designContent || `# ${opts.id}\nA design profile.\n`);
    fs.writeFileSync(path.join(dir, 'meta.json'), JSON.stringify({
        id: opts.id,
        source: opts.source || 'test',
        title: opts.title || opts.id,
        archetype: opts.archetype,
        qualityScore: opts.qualityScore,
        importedAt: new Date().toISOString(),
        checksum: 'fake-checksum',
    }, null, 2));
    if (opts.tokens) {
        fs.writeFileSync(path.join(dir, 'tokens.json'), JSON.stringify(opts.tokens, null, 2));
    }
}
function scenarioRankByIdAndArchetype() {
    const tmp = mkTmpRoot();
    try {
        seedProfile(tmp, { id: 'stripe', archetype: 'minimal-purple', qualityScore: 'A' });
        seedProfile(tmp, { id: 'vercel', archetype: 'minimal-mono', qualityScore: 'A' });
        seedProfile(tmp, { id: 'apple', archetype: 'photography-first', qualityScore: 'B' });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        const results = reg.search('minimal');
        assert(results.length === 2, `expected 2 matches for 'minimal', got ${results.length}`);
        // id matches don't count for 'minimal' — archetype meta should drive both.
        for (const r of results)
            assert(r.score >= 2, `score should be >=2 for archetype match (meta weight=2), got ${r.score}`);
        // 'apple' should NOT appear.
        assert(!results.some(r => r.profile.id === 'apple'), 'apple should not match minimal');
    }
    finally {
        rmTmp(tmp);
    }
    console.log('✅ scenario 1: search ranks by archetype meta when query matches it');
}
function scenarioFallToBody() {
    const tmp = mkTmpRoot();
    try {
        seedProfile(tmp, { id: 'foo', archetype: 'misc', designContent: '# foo\nA gorgeous brutalist composition with stark contrast.\n' });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        const r = reg.search('brutalist');
        assert(r.length === 1, `body fallback should find 1 match, got ${r.length}`);
        assert(r[0].score === 1, `body match weight should be 1, got ${r[0].score}`);
    }
    finally {
        rmTmp(tmp);
    }
    console.log('✅ scenario 2: search falls back to DESIGN.md body when meta misses');
}
function scenarioFilters() {
    const tmp = mkTmpRoot();
    try {
        seedProfile(tmp, { id: 'a', archetype: 'minimal', qualityScore: 'A', source: 'core' });
        seedProfile(tmp, { id: 'b', archetype: 'minimal', qualityScore: 'B', source: 'extracted' });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        const aOnly = reg.search('minimal', { qualityScore: 'A' });
        assert(aOnly.length === 1 && aOnly[0].profile.id === 'a', 'qualityScore filter narrows to a');
        const coreOnly = reg.search('minimal', { source: 'core' });
        assert(coreOnly.length === 1 && coreOnly[0].profile.id === 'a', 'source filter narrows to a');
    }
    finally {
        rmTmp(tmp);
    }
    console.log('✅ scenario 3: filters narrow before scoring');
}
function scenarioFindByArchetype() {
    const tmp = mkTmpRoot();
    try {
        seedProfile(tmp, { id: 'a', archetype: 'shadcn-neutral' });
        seedProfile(tmp, { id: 'b', archetype: 'apple-glass' });
        seedProfile(tmp, { id: 'c', archetype: 'shadcn-neutral' });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        const found = reg.findByArchetype('shadcn-neutral');
        assert(found.length === 2, `expected 2 shadcn-neutral, got ${found.length}`);
        assert(found.map(p => p.id).sort().join(',') === 'a,c', 'a + c matched');
    }
    finally {
        rmTmp(tmp);
    }
    console.log('✅ scenario 4: findByArchetype filters correctly');
}
function scenarioFindByTokenColor() {
    const tmp = mkTmpRoot();
    try {
        seedProfile(tmp, { id: 'blue', tokens: { colors: { primary: '#0000ff', surface: '#ffffff' } } });
        seedProfile(tmp, { id: 'red', tokens: { colors: { primary: '#ff0000' } } });
        seedProfile(tmp, { id: 'navy', tokens: { colors: { primary: '#001f3f' } } });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        // Search for #0066cc (close to blue/navy, far from red)
        const found = reg.findByTokenColor('#0066cc', 200);
        const ids = found.map(p => p.id).sort();
        assert(ids.includes('blue'), `blue should match, got ${ids.join(',')}`);
        assert(!ids.includes('red'), `red should NOT match #0066cc within deltaE=200, got ${ids.join(',')}`);
    }
    finally {
        rmTmp(tmp);
    }
    console.log('✅ scenario 5: findByTokenColor matches close-RGB profiles');
}
function scenarioDiff() {
    const tmp = mkTmpRoot();
    try {
        seedProfile(tmp, {
            id: 'a',
            archetype: 'minimal',
            qualityScore: 'A',
            tokens: { colors: { primary: '#0000ff', accent: '#ff00ff' }, typography: { body: { fontSize: '16' } } },
        });
        seedProfile(tmp, {
            id: 'b',
            archetype: 'maximalist',
            qualityScore: 'B',
            tokens: { colors: { primary: '#ff0000', accent: '#ff00ff' }, typography: { body: { fontSize: '18' } } },
        });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        const diff = reg.diff('a', 'b');
        assert(diff !== null, 'diff should not be null');
        assert(diff.archetypeChanged === true, 'archetype changed');
        assert(diff.qualityScoreChanged === true, 'quality changed');
        assert(diff.colors.length === 1, `colors should have 1 delta (primary), got ${diff.colors.length}`);
        assert(diff.colors[0].key === 'primary', `delta key should be primary, got ${diff.colors[0].key}`);
        assert(diff.colors[0].a === '#0000ff' && diff.colors[0].b === '#ff0000', 'primary delta values correct');
        assert(diff.typography.length === 1, `typography should have 1 delta (body.fontSize), got ${diff.typography.length}`);
    }
    finally {
        rmTmp(tmp);
    }
    console.log('✅ scenario 6: diff returns structured token-level deltas');
}
function scenarioDiffMissingProfile() {
    const tmp = mkTmpRoot();
    try {
        seedProfile(tmp, { id: 'a' });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        const diff = reg.diff('a', 'nonexistent');
        assert(diff === null, 'diff with missing profile must return null');
    }
    finally {
        rmTmp(tmp);
    }
    console.log('✅ scenario 7: diff handles missing profile gracefully');
}
function scenarioRealBundledCore() {
    // Smoke against the actual 5 core profiles. Skipped if no bundled core.
    const repoCore = path.join(process.cwd(), 'vendor', 'awesome-design-md-core', 'design-md');
    if (!fs.existsSync(repoCore)) {
        console.log('✓ scenario 8 skipped (no bundled core in cwd)');
        return;
    }
    const tmp = mkTmpRoot();
    try {
        // Import core into the tmp root.
        const cp = require('child_process');
        cp.execFileSync(process.execPath, [path.join(process.cwd(), 'dist', 'index.js'), 'design', 'pull', 'core'], { cwd: tmp, stdio: 'pipe' });
        const reg = new DesignMdRegistry_1.DesignMdRegistry(tmp);
        const profiles = reg.list();
        assert(profiles.length === 5, `expected 5 core profiles imported, got ${profiles.length}`);
        // Stripe should be searchable.
        const stripeResults = reg.search('stripe');
        assert(stripeResults.length >= 1, `'stripe' search should find stripe profile, got ${stripeResults.length}`);
        assert(stripeResults[0].profile.id === 'stripe', 'top hit for "stripe" should be stripe');
        // Diff apple vs claude should produce some delta.
        const diff = reg.diff('apple', 'claude');
        assert(diff !== null, 'apple↔claude diff should not be null');
        const totalDeltas = diff.colors.length + diff.typography.length;
        assert(totalDeltas > 0, `apple↔claude should have some color/typo deltas, got ${totalDeltas}`);
        console.log(`✅ scenario 8: real bundled core — 5 profiles, search('stripe')=stripe, apple↔claude delta=${totalDeltas}`);
    }
    finally {
        rmTmp(tmp);
    }
}
try {
    scenarioRankByIdAndArchetype();
    scenarioFallToBody();
    scenarioFilters();
    scenarioFindByArchetype();
    scenarioFindByTokenColor();
    scenarioDiff();
    scenarioDiffMissingProfile();
    scenarioRealBundledCore();
    console.log('TEST_DESIGN_REGISTRY_SEARCH_OK');
}
catch (err) {
    console.error('TEST_DESIGN_REGISTRY_SEARCH_FAIL', err);
    process.exit(1);
}
