"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.characterEngine = exports.CharacterEngine = void 0;
const logger_js_1 = require("../../utils/logger.js");
const index_js_1 = require("../data-store/index.js");
const dna_schema_js_1 = require("./dna-schema.js");
const prompt_builder_js_1 = require("./prompt-builder.js");
const reference_pipeline_js_1 = require("./reference-pipeline.js");
const clone_js_1 = require("./clone.js");
const index_js_2 = require("../persona-generator/index.js");
const log = (0, logger_js_1.createModuleLogger)('character-engine');
class CharacterEngine {
    /**
     * Full creation pipeline:
     * 1. Fill defaults & validate DNA
     * 2. Save character with 'creating' status
     * 3. Generate Master JSON Prompt
     * 4. Generate reference images (queued)
     * 5. Save conversation profile if provided
     * 6. Set status to 'active'
     */
    async createCharacter(partial, profile) {
        // Step 1: Fill defaults and validate
        const dna = (0, dna_schema_js_1.fillDefaults)({ ...partial, status: 'creating' });
        const validation = (0, dna_schema_js_1.validateDNA)(dna);
        if (!validation.valid) {
            throw new Error(`Invalid character DNA: ${validation.errors.join('; ')}`);
        }
        log.info({ characterId: dna.id, name: dna.identity.name }, 'Creating character');
        // Step 2: Save character with 'creating' status
        await index_js_1.dataStore.saveCharacter(dna);
        try {
            // Step 3: Generate and save Master JSON Prompt
            const masterPrompt = (0, prompt_builder_js_1.buildMasterPrompt)(dna);
            await index_js_1.dataStore.saveMasterPrompt(masterPrompt);
            // Step 4: Queue reference image generation
            await (0, reference_pipeline_js_1.generateReferenceImages)(dna.id, dna);
            // Step 5: Save conversation profile if provided
            let fullProfile;
            if (profile) {
                fullProfile = buildConversationProfile(dna.id, profile);
                await index_js_1.dataStore.saveConversationProfile(fullProfile);
            }
            // Step 5.5: Fire-and-forget persona generation
            index_js_2.personaGenerator.generate(dna, fullProfile)
                .then(async (persona) => {
                if (persona) {
                    await index_js_1.dataStore.saveConversationPersona(dna.id, persona);
                    log.info({ characterId: dna.id }, 'Persona generated and saved');
                }
            })
                .catch((err) => {
                const message = err instanceof Error ? err.message : String(err);
                log.error({ characterId: dna.id, error: message }, 'Persona generation failed (non-blocking)');
            });
            // Step 6: Set status to active
            dna.status = 'active';
            dna.updatedAt = new Date().toISOString();
            await index_js_1.dataStore.saveCharacter(dna);
            log.info({ characterId: dna.id }, 'Character created successfully');
            return dna;
        }
        catch (err) {
            log.error({ characterId: dna.id, err: err.message }, 'Character creation failed');
            throw err;
        }
    }
    /**
     * Update DNA fields for an existing character.
     */
    async updateCharacter(id, updates) {
        const existing = await index_js_1.dataStore.getCharacter(id);
        if (!existing) {
            throw new Error(`Character not found: ${id}`);
        }
        const updated = mergeCharacterDNA(existing, updates);
        updated.updatedAt = new Date().toISOString();
        const validation = (0, dna_schema_js_1.validateDNA)(updated);
        if (!validation.valid) {
            throw new Error(`Invalid character DNA after update: ${validation.errors.join('; ')}`);
        }
        await index_js_1.dataStore.saveCharacter(updated);
        log.info({ characterId: id }, 'Character updated');
        return updated;
    }
    /**
     * Delete a character and all associated data.
     */
    async deleteCharacter(id) {
        const deleted = await index_js_1.dataStore.deleteCharacter(id);
        if (deleted) {
            log.info({ characterId: id }, 'Character deleted');
        }
        return deleted;
    }
    /**
     * Get character details by ID.
     */
    async getCharacter(id) {
        return index_js_1.dataStore.getCharacter(id);
    }
    /**
     * List all characters.
     */
    async listCharacters() {
        return index_js_1.dataStore.listCharacters();
    }
    /**
     * Set character status to 'active'.
     */
    async activateCharacter(id) {
        return this.setStatus(id, 'active');
    }
    /**
     * Set character status to 'inactive'.
     */
    async deactivateCharacter(id) {
        return this.setStatus(id, 'inactive');
    }
    /**
     * Clone an existing character. Delegates to clone module.
     */
    async cloneCharacter(sourceId, overrides) {
        return (0, clone_js_1.cloneCharacter)(sourceId, overrides);
    }
    async setStatus(id, status) {
        const existing = await index_js_1.dataStore.getCharacter(id);
        if (!existing) {
            throw new Error(`Character not found: ${id}`);
        }
        existing.status = status;
        existing.updatedAt = new Date().toISOString();
        await index_js_1.dataStore.saveCharacter(existing);
        log.info({ characterId: id, status }, 'Character status changed');
        return existing;
    }
}
exports.CharacterEngine = CharacterEngine;
/** Shallow-merge top-level DNA sections, preserving nested structure. */
function mergeCharacterDNA(base, updates) {
    const merged = { ...base };
    // Merge each section if provided
    if (updates.identity)
        merged.identity = { ...base.identity, ...updates.identity };
    if (updates.physicalMeasurements) {
        merged.physicalMeasurements = {
            ...base.physicalMeasurements,
            ...updates.physicalMeasurements,
            measurements: {
                ...base.physicalMeasurements.measurements,
                ...updates.physicalMeasurements.measurements,
            },
        };
    }
    if (updates.skinMap)
        merged.skinMap = { ...base.skinMap, ...updates.skinMap };
    if (updates.faceAnatomy)
        merged.faceAnatomy = { ...base.faceAnatomy, ...updates.faceAnatomy };
    if (updates.hairDNA)
        merged.hairDNA = { ...base.hairDNA, ...updates.hairDNA };
    if (updates.bodyBiometrics)
        merged.bodyBiometrics = { ...base.bodyBiometrics, ...updates.bodyBiometrics };
    if (updates.profileView)
        merged.profileView = { ...base.profileView, ...updates.profileView };
    if (updates.expressionMotion)
        merged.expressionMotion = { ...base.expressionMotion, ...updates.expressionMotion };
    if (updates.makeupStyle) {
        merged.makeupStyle = {
            ...base.makeupStyle,
            ...updates.makeupStyle,
            colors: {
                ...base.makeupStyle.colors,
                ...updates.makeupStyle.colors,
            },
        };
    }
    if (updates.fashionStyle)
        merged.fashionStyle = { ...base.fashionStyle, ...updates.fashionStyle };
    if (updates.technicalSettings)
        merged.technicalSettings = { ...base.technicalSettings, ...updates.technicalSettings };
    if (updates.status)
        merged.status = updates.status;
    return merged;
}
/** Build a full ConversationProfile with defaults. */
function buildConversationProfile(characterId, partial) {
    return {
        characterId,
        style: partial.style ?? 'neseli',
        customStyleDescription: partial.customStyleDescription,
        toneOfVoice: {
            formality: partial.toneOfVoice?.formality ?? 'casual',
            emoji_frequency: partial.toneOfVoice?.emoji_frequency ?? 'medium',
            message_length: partial.toneOfVoice?.message_length ?? 'medium',
            humor_level: partial.toneOfVoice?.humor_level ?? 'subtle',
            flirtation_level: partial.toneOfVoice?.flirtation_level ?? 'subtle',
        },
        languagePatterns: {
            common_phrases: partial.languagePatterns?.common_phrases ?? [],
            filler_words: partial.languagePatterns?.filler_words ?? [],
            reaction_templates: partial.languagePatterns?.reaction_templates ?? {},
        },
        salesBehavior: {
            min_messages_before_pitch: partial.salesBehavior?.min_messages_before_pitch ?? 10,
            cooldown_minutes: partial.salesBehavior?.cooldown_minutes ?? 60,
            pitch_style: partial.salesBehavior?.pitch_style ?? 'subtle',
        },
    };
}
exports.characterEngine = new CharacterEngine();
//# sourceMappingURL=index.js.map