"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 SessionFollowupService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionFollowupService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const fs = require("fs/promises");
const path = require("path");
const core_entities_1 = require("../core-entities");
const sessions_service_1 = require("../sessions/sessions.service");
let SessionFollowupService = SessionFollowupService_1 = class SessionFollowupService {
    constructor(sessionsRepository, contextTemplatesRepository, sessionInputsRepository, sessionsService) {
        this.sessionsRepository = sessionsRepository;
        this.contextTemplatesRepository = contextTemplatesRepository;
        this.sessionInputsRepository = sessionInputsRepository;
        this.sessionsService = sessionsService;
        this.logger = new common_1.Logger(SessionFollowupService_1.name);
        this.projectRoot = process.env.REPOBURG_PROJECT_PATH || process.cwd();
    }
    resolveAndValidatePath(unsafePath) {
        const normalizedPath = path.normalize(unsafePath);
        if (path.isAbsolute(normalizedPath)) {
            throw new common_1.BadRequestException(`Absolute paths are not allowed: ${unsafePath}`);
        }
        const resolvedPath = path.resolve(this.projectRoot, normalizedPath);
        if (!resolvedPath.startsWith(this.projectRoot)) {
            this.logger.warn(`Path traversal attempt detected: ${unsafePath}`);
            throw new common_1.BadRequestException(`Path traversal is not allowed. Access denied for path: ${unsafePath}`);
        }
        return resolvedPath;
    }
    async createFromContext(sessionId, createDto) {
        const sourceSession = await this.sessionsRepository.findOne({
            where: { id: sessionId },
            relations: ['sessionInputs', 'sessionInputs.aiActions'],
        });
        if (!sourceSession) {
            throw new common_1.NotFoundException(`Source session with ID "${sessionId}" not found.`);
        }
        this.logger.log(`Creating new session from context of session ${sessionId}`);
        const filePaths = new Set();
        const folderPaths = new Set();
        for (const input of sourceSession.sessionInputs) {
            if (input.ad_hoc_context_definition) {
                try {
                    const adhocContext = JSON.parse(input.ad_hoc_context_definition);
                    if (adhocContext.files && Array.isArray(adhocContext.files)) {
                        adhocContext.files.forEach((f) => filePaths.add(f));
                    }
                    if (adhocContext.folders && Array.isArray(adhocContext.folders)) {
                        adhocContext.folders.forEach((f) => folderPaths.add(f));
                    }
                }
                catch (e) {
                    this.logger.warn(`Could not parse ad_hoc_context_definition for input ${input.id}`);
                }
            }
            for (const action of input.aiActions) {
                if ((action.action_type === 'create_file' ||
                    action.action_type === 'overwrite_file' ||
                    action.action_type === 'patch') &&
                    action.file_path) {
                    filePaths.add(action.file_path);
                }
                else if (action.action_type === 'request_context') {
                    if (action.files) {
                        action.files
                            .split(',')
                            .map((f) => f.trim())
                            .filter(Boolean)
                            .forEach((f) => filePaths.add(f));
                    }
                    if (action.folders) {
                        action.folders
                            .split(',')
                            .map((f) => f.trim())
                            .filter(Boolean)
                            .forEach((f) => folderPaths.add(f));
                    }
                }
            }
        }
        const validatedFiles = [];
        for (const filePath of filePaths) {
            try {
                const safePath = this.resolveAndValidatePath(filePath);
                await fs.access(safePath);
                validatedFiles.push(filePath);
            }
            catch (error) {
                this.logger.warn(`File "${filePath}" from source session context not found on filesystem, skipping.`);
            }
        }
        const validatedFolders = [];
        for (const folderPath of folderPaths) {
            try {
                const safePath = this.resolveAndValidatePath(folderPath);
                const stats = await fs.stat(safePath);
                if (stats.isDirectory()) {
                    validatedFolders.push(folderPath);
                }
            }
            catch (error) {
                this.logger.warn(`Folder "${folderPath}" from source session context not found on filesystem, skipping.`);
            }
        }
        let initialTemplateForFollowup = await this.contextTemplatesRepository.findOneBy({
            is_default_condensed: true,
        });
        if (initialTemplateForFollowup) {
            this.logger.log(`Using default condensed template "${initialTemplateForFollowup.template_name}" as initial template for new follow-up session.`);
        }
        else {
            this.logger.log(`No default condensed template found. Falling back to default initial template.`);
            initialTemplateForFollowup =
                await this.contextTemplatesRepository.findOneBy({
                    is_default_initial: true,
                });
            if (initialTemplateForFollowup) {
                this.logger.log(`Using default initial template "${initialTemplateForFollowup.template_name}" for new follow-up session.`);
            }
        }
        const createSessionPayload = {
            session_title: createDto.session_title,
        };
        if (initialTemplateForFollowup) {
            createSessionPayload.default_initial_context_template_id =
                initialTemplateForFollowup.id;
        }
        else {
            this.logger.log(`No default condensed or initial template found for follow-up session.`);
        }
        const newSession = await this.sessionsService.create(createSessionPayload);
        if (validatedFiles.length > 0 || validatedFolders.length > 0) {
            const contextDefinition = {
                files: validatedFiles,
                folders: validatedFolders,
            };
            const newSessionInput = this.sessionInputsRepository.create({
                session_id: newSession.id,
                user_prompt: 'Inherited context from previous session.',
                ad_hoc_context_definition: JSON.stringify(contextDefinition),
                generated_context_string: '',
                execution_strategy: 'review_first',
                raw_llm_response: null,
                is_context_carrier: true,
            });
            await this.sessionInputsRepository.save(newSessionInput);
            this.logger.log(`Created initial SessionInput with inherited context for new session ${newSession.id}`);
        }
        return this.sessionsService.findOne(newSession.id);
    }
};
exports.SessionFollowupService = SessionFollowupService;
exports.SessionFollowupService = SessionFollowupService = SessionFollowupService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(core_entities_1.Session)),
    __param(1, (0, typeorm_1.InjectRepository)(core_entities_1.ContextTemplate)),
    __param(2, (0, typeorm_1.InjectRepository)(core_entities_1.SessionInput)),
    __param(3, (0, common_1.Inject)((0, common_1.forwardRef)(() => sessions_service_1.SessionsService))),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        sessions_service_1.SessionsService])
], SessionFollowupService);
//# sourceMappingURL=session-followup.service.js.map