"use strict";
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;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var ContextTemplatesService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContextTemplatesService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const core_entities_1 = require("../core-entities");
const context_generation_service_1 = require("../context-generation/context-generation.service");
const gpt_tokenizer_1 = require("gpt-tokenizer");
const custom_variables_service_1 = require("../custom-variables/custom-variables.service");
let ContextTemplatesService = ContextTemplatesService_1 = class ContextTemplatesService {
    constructor(contextTemplatesRepository, dataSource, contextGenerationService, customVariablesService) {
        this.contextTemplatesRepository = contextTemplatesRepository;
        this.dataSource = dataSource;
        this.contextGenerationService = contextGenerationService;
        this.customVariablesService = customVariablesService;
        this.logger = new common_1.Logger(ContextTemplatesService_1.name);
    }
    async create(createContextTemplateDto) {
        const template = this.contextTemplatesRepository.create(createContextTemplateDto);
        return this.contextTemplatesRepository.save(template);
    }
    async findAll(type) {
        const where = {};
        if (type) {
            where.template_type = type;
        }
        return this.contextTemplatesRepository.find({
            where,
            order: { template_name: 'ASC' },
        });
    }
    async findOne(id) {
        const template = await this.contextTemplatesRepository.findOneBy({ id });
        if (!template) {
            throw new common_1.NotFoundException(`ContextTemplate with ID "${id}" not found`);
        }
        return template;
    }
    async findByName(name) {
        return this.contextTemplatesRepository.findOneBy({ template_name: name });
    }
    async findByBuiltinKey(builtinKey) {
        return this.contextTemplatesRepository.findOneBy({
            builtin_key: builtinKey,
        });
    }
    async findDefaultInitial() {
        return this.contextTemplatesRepository.findOneBy({
            is_default_initial: true,
        });
    }
    async findDefaultFollowup() {
        return this.contextTemplatesRepository.findOneBy({
            is_default_followup: true,
        });
    }
    async update(id, updateContextTemplateDto) {
        const template = await this.findOne(id);
        if (template.is_builtin) {
            throw new common_1.ForbiddenException(`Cannot modify built-in context template "${template.template_name}". Duplicate it to create your own version.`);
        }
        const { template_name, template_content, context_definition, template_type, } = updateContextTemplateDto;
        this.contextTemplatesRepository.merge(template, {
            template_name,
            template_content,
            context_definition,
            template_type,
        });
        return this.contextTemplatesRepository.save(template);
    }
    async remove(id) {
        const template = await this.findOne(id);
        await this.contextTemplatesRepository.remove(template);
    }
    async duplicate(id) {
        const originalTemplate = await this.findOne(id);
        let newName = `${originalTemplate.template_name} (Copy)`;
        let suffix = 2;
        while (await this.contextTemplatesRepository.findOneBy({
            template_name: newName,
        })) {
            newName = `${originalTemplate.template_name} (Copy ${suffix})`;
            suffix++;
        }
        const duplicate = this.contextTemplatesRepository.create({
            template_name: newName,
            template_content: originalTemplate.template_content,
            context_definition: originalTemplate.context_definition,
            template_type: originalTemplate.template_type,
            is_builtin: false,
            builtin_key: null,
        });
        return this.contextTemplatesRepository.save(duplicate);
    }
    async updateBuiltinContent(id, templateContent) {
        const template = await this.contextTemplatesRepository.findOneBy({ id });
        if (!template) {
            throw new common_1.NotFoundException(`ContextTemplate with ID "${id}" not found`);
        }
        template.template_content = templateContent;
        return this.contextTemplatesRepository.save(template);
    }
    async preview(dto) {
        const adHocData = {
            adhoc_files_content: '',
            adhoc_folders_content: '',
        };
        if (dto.context_definition) {
            if (dto.context_definition.files &&
                dto.context_definition.files.length > 0) {
                const fileContents = await Promise.all(dto.context_definition.files.map((filePath) => this.contextGenerationService.secureReadFile(filePath)));
                adHocData.adhoc_files_content = fileContents.join('\n\n');
            }
            if (dto.context_definition.folders &&
                dto.context_definition.folders.length > 0) {
                const folderContexts = await Promise.all(dto.context_definition.folders.map(async (folderPath) => {
                    const tree = await this.contextGenerationService.secureTree(folderPath);
                    const header = `// Tree for: ${folderPath}\n\`\`\`\n${tree}\n\`\`\``;
                    const filesInFolder = await this.contextGenerationService.secureGlob(`${folderPath}/**/*`);
                    const fileContents = await Promise.all(filesInFolder.map((filePath) => this.contextGenerationService.secureReadFile(filePath)));
                    return [header, ...fileContents].join('\n\n');
                }));
                adHocData.adhoc_folders_content = folderContexts.join('\n\n---\n\n');
            }
        }
        const enabledVariables = await this.customVariablesService.findAllEnabled();
        const variableMap = enabledVariables.reduce((acc, curr) => {
            acc[curr.key] = curr.value;
            return acc;
        }, {});
        const data = {
            ...adHocData,
            user_input: '',
            system_prompt: '',
            ad_hoc_context_definition: JSON.stringify(dto.context_definition || {}),
            VAR: variableMap,
        };
        const rendered_context = await this.contextGenerationService.render(dto.template_content, data);
        const token_count = (0, gpt_tokenizer_1.countTokens)(rendered_context);
        return {
            rendered_context,
            token_count,
        };
    }
    async setDefaultInitial(id) {
        const newDefault = await this.findOne(id);
        await this.dataSource.transaction(async (manager) => {
            const currentDefault = await manager.findOneBy(core_entities_1.ContextTemplate, {
                is_default_initial: true,
            });
            if (currentDefault && currentDefault.id !== newDefault.id) {
                currentDefault.is_default_initial = false;
                await manager.save(currentDefault);
            }
            if (!newDefault.is_default_initial) {
                newDefault.is_default_initial = true;
                await manager.save(newDefault);
            }
        });
        return newDefault;
    }
    async setDefaultFollowup(id) {
        const newDefault = await this.findOne(id);
        await this.dataSource.transaction(async (manager) => {
            const currentDefault = await manager.findOneBy(core_entities_1.ContextTemplate, {
                is_default_followup: true,
            });
            if (currentDefault && currentDefault.id !== newDefault.id) {
                currentDefault.is_default_followup = false;
                await manager.save(currentDefault);
            }
            if (!newDefault.is_default_followup) {
                newDefault.is_default_followup = true;
                await manager.save(newDefault);
            }
        });
        return newDefault;
    }
    async setDefaultCondensed(id) {
        const newDefault = await this.findOne(id);
        await this.dataSource.transaction(async (manager) => {
            const currentDefault = await manager.findOneBy(core_entities_1.ContextTemplate, {
                is_default_condensed: true,
            });
            if (currentDefault && currentDefault.id !== newDefault.id) {
                currentDefault.is_default_condensed = false;
                await manager.save(currentDefault);
            }
            if (!newDefault.is_default_condensed) {
                newDefault.is_default_condensed = true;
                await manager.save(newDefault);
            }
        });
        return newDefault;
    }
};
exports.ContextTemplatesService = ContextTemplatesService;
exports.ContextTemplatesService = ContextTemplatesService = ContextTemplatesService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(core_entities_1.ContextTemplate)),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.DataSource,
        context_generation_service_1.ContextGenerationService,
        custom_variables_service_1.CustomVariablesService])
], ContextTemplatesService);
//# sourceMappingURL=context-templates.service.js.map