import { config } from "../../config.js";
export class FormService {
    repo;
    cache;
    constructor(repo, cache) {
        this.repo = repo;
        this.cache = cache;
    }
    async listForms() {
        const key = "forms:list";
        const cached = await this.cache.get(key);
        if (cached)
            return cached;
        const forms = await this.repo.listForms();
        await this.cache.set(key, forms, config.schemaTtlSeconds);
        return forms;
    }
    async getFormByCode(code) {
        const key = `forms:detail:${code}`;
        const cached = await this.cache.get(key);
        if (cached)
            return cached;
        const form = await this.repo.getFormByCode(code);
        if (form) {
            await this.cache.set(key, form, config.schemaTtlSeconds);
        }
        return form;
    }
    /**
     * Legacy-compat: return the surveyJson of the requested version.
     * Kept for the GET /api/forms/schema endpoint.
     */
    async getSchema(formCode, version) {
        const cacheKey = `forms:schema:${formCode}:${version}`;
        const cached = await this.cache.get(cacheKey);
        if (cached)
            return cached;
        const form = await this.getFormByCode(formCode);
        if (!form)
            throw new Error(`Form "${formCode}" not found`);
        const ver = form.versions.find((v) => v.semver === version);
        if (!ver)
            throw new Error(`Version "${version}" not found for form "${formCode}"`);
        await this.cache.set(cacheKey, ver.surveyJson, config.schemaTtlSeconds);
        return ver.surveyJson;
    }
    async createForm(data) {
        const form = await this.repo.createForm(data);
        await this.cache.delByPrefix("forms:list");
        return form;
    }
    async updateForm(code, data) {
        const form = await this.repo.updateForm(code, data);
        if (form) {
            await Promise.all([
                this.cache.delByPrefix(`forms:detail:${code}`),
                this.cache.delByPrefix(`forms:schema:${code}:`),
                this.cache.delByPrefix("forms:list"),
            ]);
        }
        return form;
    }
    async deleteForm(code) {
        const deleted = await this.repo.softDeleteForm(code);
        if (deleted) {
            await Promise.all([
                this.cache.delByPrefix(`forms:detail:${code}`),
                this.cache.delByPrefix(`forms:schema:${code}:`),
                this.cache.delByPrefix("forms:list"),
            ]);
        }
        return deleted;
    }
    async publishVersion(formCode, data) {
        const form = await this.repo.getFormByCode(formCode);
        if (!form)
            throw new Error(`Form "${formCode}" not found`);
        const version = await this.repo.publishVersion(form.id, data);
        // Invalidate caches
        await Promise.all([
            this.cache.delByPrefix(`forms:detail:${formCode}`),
            this.cache.delByPrefix(`forms:schema:${formCode}:`),
        ]);
        return version;
    }
    async submit(formCode, version, moduleCode, answers, submittedBy) {
        const form = await this.getFormByCode(formCode);
        if (!form)
            throw new Error(`Form "${formCode}" not found`);
        const ver = form.versions.find((v) => v.semver === version);
        if (!ver)
            throw new Error(`Version "${version}" not found for form "${formCode}"`);
        // Validate answer keys against questionIndex
        const knownKeys = Object.keys(ver.questionIndex);
        if (knownKeys.length > 0) {
            for (const key of Object.keys(answers)) {
                if (!ver.questionIndex[key]) {
                    throw new Error(`Unknown question key: ${key}`);
                }
            }
        }
        const input = {
            formId: form.id,
            formVersionId: ver.id,
            schemaChecksum: ver.schemaChecksum,
            moduleCode,
            submittedBy,
            answers,
        };
        return this.repo.saveSubmission(input);
    }
    async listSubmissions(formId, filter) {
        return this.repo.listSubmissions(formId, filter);
    }
}
