"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: Object.getOwnPropertyDescriptor(all, name).get
    });
}
_export(exports, {
    get noteListHandler () {
        return noteListHandler;
    },
    get notesWithSingleItemListHandler () {
        return notesWithSingleItemListHandler;
    }
});
const _sequelize = /*#__PURE__*/ _interop_require_wildcard(require("sequelize"));
const _expressasynchandler = /*#__PURE__*/ _interop_require_default(require("express-async-handler"));
const _constants = require("@tamanu/constants");
const _checkNotePermission = require("../../utils/checkNotePermission");
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
function _getRequireWildcardCache(nodeInterop) {
    if (typeof WeakMap !== "function") return null;
    var cacheBabelInterop = new WeakMap();
    var cacheNodeInterop = new WeakMap();
    return (_getRequireWildcardCache = function(nodeInterop) {
        return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
    })(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
    if (!nodeInterop && obj && obj.__esModule) {
        return obj;
    }
    if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
        return {
            default: obj
        };
    }
    var cache = _getRequireWildcardCache(nodeInterop);
    if (cache && cache.has(obj)) {
        return cache.get(obj);
    }
    var newObj = {
        __proto__: null
    };
    var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
    for(var key in obj){
        if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
            var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
            if (desc && (desc.get || desc.set)) {
                Object.defineProperty(newObj, key, desc);
            } else {
                newObj[key] = obj[key];
            }
        }
    }
    newObj.default = obj;
    if (cache) {
        cache.set(obj, newObj);
    }
    return newObj;
}
const noteListHandler = (recordType)=>(0, _expressasynchandler.default)(async (req, res)=>{
        const { models, params, query } = req;
        const { order = 'ASC', orderBy, noteTypeId, rowsPerPage, page } = query;
        const recordId = params.id;
        await (0, _checkNotePermission.checkNotePermission)(req, {
            recordType,
            recordId
        }, 'list');
        const include = [
            {
                model: models.User,
                as: 'author'
            },
            {
                model: models.User,
                as: 'onBehalfOf'
            },
            {
                model: models.ReferenceData,
                as: 'noteTypeReference'
            },
            {
                model: models.Note,
                as: 'revisedBy',
                required: false,
                attributes: [
                    'date'
                ],
                include: [
                    {
                        model: models.User,
                        as: 'author'
                    },
                    {
                        model: models.User,
                        as: 'onBehalfOf'
                    }
                ]
            }
        ];
        const idRows = await models.Note.sequelize.query(`
      WITH

      -- first create a sub-table with only the notes for this record.
      -- this will make the DISTINCT stuff way faster
      this_record_notes AS (
        SELECT
          *,
          CASE WHEN revised_by_id IS NULL THEN id ELSE revised_by_id END edit_chain
        FROM notes n
        WHERE record_type = :recordType
          AND record_id = :recordId
          AND deleted_at IS NULL
      )

      -- now filter out anything except the latest revision for each note
      SELECT DISTINCT ON (edit_chain)
        id
      FROM this_record_notes n
      ORDER BY edit_chain, date DESC
    `, {
            type: _sequelize.QueryTypes.SELECT,
            replacements: {
                recordType,
                recordId
            }
        });
        // any other filtering should happen after the edits have been determined
        // (if we do it all in the same step, we risk including earlier versions of
        // a record that was excluded later, which we absolutely do not want)
        const where = {
            id: {
                [_sequelize.Op.in]: idRows.map((x)=>x.id)
            },
            visibilityStatus: _constants.VISIBILITY_STATUSES.CURRENT,
            ...noteTypeId ? {
                noteTypeId
            } : {}
        };
        const queryOrder = orderBy ? [
            [
                orderBy,
                order.toUpperCase()
            ]
        ] : [
            [
                // Pin TREATMENT_PLAN on top
                _sequelize.default.literal(`case when "Note"."note_type_id" = '${_constants.NOTE_TYPES.TREATMENT_PLAN}' then 0 else 1 end`)
            ],
            [
                // If the note has already been revised then order by the root note's date.
                // If this is the root note then order by the date of this note
                _sequelize.default.literal('case when "revisedBy"."date" notnull then "revisedBy"."date" else "Note"."date" end desc')
            ]
        ];
        const rows = await models.Note.findAll({
            include,
            where,
            order: queryOrder,
            limit: rowsPerPage,
            offset: page && rowsPerPage ? page * rowsPerPage : undefined
        });
        const totalCount = await models.Note.count({
            where
        });
        const editChains = [
            ...new Set(rows.map((n)=>n.revisedById ?? n.id))
        ];
        if (editChains.length > 0) {
            const chainCounts = await models.Note.sequelize.query(`
        SELECT
          CASE WHEN revised_by_id IS NULL THEN id ELSE revised_by_id END AS chain_id,
          COUNT(*) AS count
        FROM notes
        WHERE record_type = :recordType
          AND record_id = :recordId
          AND deleted_at IS NULL
          AND (CASE WHEN revised_by_id IS NULL THEN id ELSE revised_by_id END) IN (:editChains)
        GROUP BY chain_id
        `, {
                type: _sequelize.QueryTypes.SELECT,
                replacements: {
                    recordType,
                    recordId,
                    editChains
                }
            });
            const countByChain = Object.fromEntries(chainCounts.map(({ chain_id, count })=>[
                    chain_id,
                    Number(count)
                ]));
            rows.forEach((note)=>{
                const chainId = note.revisedById ?? note.id;
                const totalInChain = countByChain[chainId] ?? 1;
                note.setDataValue('editCount', Math.max(0, totalInChain - 1));
            });
        }
        res.send({
            data: rows,
            count: totalCount
        });
    });
const notesWithSingleItemListHandler = (recordType)=>(0, _expressasynchandler.default)(async (req, res)=>{
        const { models, params } = req;
        const recordId = params.id;
        await (0, _checkNotePermission.checkNotePermission)(req, {
            recordType,
            recordId
        }, 'list');
        const notes = await models.Note.findAll({
            include: [
                {
                    model: models.User,
                    as: 'author'
                },
                {
                    model: models.User,
                    as: 'onBehalfOf'
                },
                {
                    model: models.ReferenceData,
                    as: 'noteTypeReference'
                }
            ],
            where: {
                recordId,
                recordType,
                visibilityStatus: _constants.VISIBILITY_STATUSES.CURRENT
            },
            order: [
                [
                    'date',
                    'DESC'
                ]
            ]
        });
        res.send({
            data: notes,
            count: notes.length
        });
    });

//# sourceMappingURL=noteListHandler.js.map