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); }
};
import { Resolver, Mutation, Arg, Ctx } from "type-graphql";
import { ActionEngineServer } from "@memberjunction/actions";
import { EntityActionEngineServer } from "@memberjunction/actions";
import { CompositeKey, KeyValuePair, LogError } from "@memberjunction/core";
import { Field, InputType, ObjectType } from "type-graphql";
import { KeyValuePairInput } from "../generic/KeyValuePairInput.js";
import { CopyScalarsAndArrays } from "@memberjunction/global";
import { GetReadOnlyProvider } from "../util.js";
let ActionParamInput = class ActionParamInput {
    Name;
    Value;
    Type;
};
__decorate([
    Field(),
    __metadata("design:type", String)
], ActionParamInput.prototype, "Name", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", String)
], ActionParamInput.prototype, "Value", void 0);
__decorate([
    Field(),
    __metadata("design:type", String)
], ActionParamInput.prototype, "Type", void 0);
ActionParamInput = __decorate([
    InputType()
], ActionParamInput);
export { ActionParamInput };
let RunActionInput = class RunActionInput {
    ActionID;
    Params;
    SkipActionLog;
};
__decorate([
    Field(),
    __metadata("design:type", String)
], RunActionInput.prototype, "ActionID", void 0);
__decorate([
    Field(() => [ActionParamInput], { nullable: true }),
    __metadata("design:type", Array)
], RunActionInput.prototype, "Params", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], RunActionInput.prototype, "SkipActionLog", void 0);
RunActionInput = __decorate([
    InputType()
], RunActionInput);
export { RunActionInput };
let CompositeKeyInput = class CompositeKeyInput {
    KeyValuePairs;
};
__decorate([
    Field(() => [KeyValuePairInput]),
    __metadata("design:type", Array)
], CompositeKeyInput.prototype, "KeyValuePairs", void 0);
CompositeKeyInput = __decorate([
    InputType()
], CompositeKeyInput);
export { CompositeKeyInput };
let EntityActionInput = class EntityActionInput {
    EntityActionID;
    InvocationType;
    EntityName;
    EntityID;
    PrimaryKey;
    ListID;
    ViewID;
    Params;
};
__decorate([
    Field(),
    __metadata("design:type", String)
], EntityActionInput.prototype, "EntityActionID", void 0);
__decorate([
    Field(),
    __metadata("design:type", String)
], EntityActionInput.prototype, "InvocationType", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], EntityActionInput.prototype, "EntityName", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], EntityActionInput.prototype, "EntityID", void 0);
__decorate([
    Field(() => CompositeKeyInput, { nullable: true }),
    __metadata("design:type", CompositeKeyInput)
], EntityActionInput.prototype, "PrimaryKey", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], EntityActionInput.prototype, "ListID", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], EntityActionInput.prototype, "ViewID", void 0);
__decorate([
    Field(() => [ActionParamInput], { nullable: true }),
    __metadata("design:type", Array)
], EntityActionInput.prototype, "Params", void 0);
EntityActionInput = __decorate([
    InputType()
], EntityActionInput);
export { EntityActionInput };
let ActionResultOutput = class ActionResultOutput {
    Success;
    Message;
    ResultCode;
    ResultData;
};
__decorate([
    Field(),
    __metadata("design:type", Boolean)
], ActionResultOutput.prototype, "Success", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", String)
], ActionResultOutput.prototype, "Message", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], ActionResultOutput.prototype, "ResultCode", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], ActionResultOutput.prototype, "ResultData", void 0);
ActionResultOutput = __decorate([
    ObjectType()
], ActionResultOutput);
export { ActionResultOutput };
let ActionResolver = class ActionResolver {
    async RunAction(input, ctx) {
        try {
            const user = ctx.userPayload.userRecord;
            if (!user) {
                throw new Error("User is not authenticated");
            }
            await ActionEngineServer.Instance.Config(false, user);
            const action = this.findActionById(input.ActionID);
            const params = this.parseActionParameters(input.Params);
            const result = await this.executeAction(action, user, params, input.SkipActionLog);
            return this.createActionResult(result);
        }
        catch (e) {
            return this.handleActionError(e);
        }
    }
    findActionById(actionID) {
        const action = ActionEngineServer.Instance.Actions.find(a => a.ID === actionID);
        if (!action) {
            throw new Error(`Action with ID ${actionID} not found`);
        }
        return action;
    }
    parseActionParameters(inputParams) {
        if (!inputParams || inputParams.length === 0) {
            return [];
        }
        return inputParams.map(p => {
            let value = p.Value;
            try {
                if (p.Value && (p.Type === 'object' || p.Type === 'array')) {
                    value = JSON.parse(p.Value);
                }
            }
            catch (e) {
                const error = e;
                LogError(`Failed to parse parameter value as JSON: ${error.message}`);
            }
            return {
                Name: p.Name,
                Value: value,
                Type: 'Input'
            };
        });
    }
    async executeAction(action, user, params, skipActionLog) {
        return await ActionEngineServer.Instance.RunAction({
            Action: action,
            ContextUser: user,
            Params: params,
            SkipActionLog: skipActionLog,
            Filters: []
        });
    }
    createActionResult(result) {
        const x = (result.Params || result.RunParams.Params || [])
            .filter(p => p.Type.trim().toLowerCase() === 'output' ||
            p.Type.trim().toLowerCase() === 'both');
        return {
            Success: result.Success,
            Message: result.Message,
            ResultCode: result.Result?.ResultCode,
            ResultData: x && x.length > 0 ? JSON.stringify(CopyScalarsAndArrays(x)) : undefined
        };
    }
    handleActionError(e) {
        const error = e;
        LogError(`Error in RunAction resolver: ${error}`);
        return {
            Success: false,
            Message: `Error executing action: ${error.message}`
        };
    }
    async RunEntityAction(input, ctx) {
        try {
            const user = ctx.userPayload.userRecord;
            if (!user) {
                throw new Error("User is not authenticated");
            }
            await EntityActionEngineServer.Instance.Config(false, user);
            const entityAction = this.getEntityAction(input.EntityActionID);
            const params = this.createBaseParams(entityAction, input.InvocationType, user);
            if ((input.EntityID || input.EntityName) && input.PrimaryKey && input.PrimaryKey.KeyValuePairs.length > 0) {
                await this.addEntityObject(ctx.providers, params, input, user);
            }
            this.addOptionalParams(params, input);
            const result = await EntityActionEngineServer.Instance.RunEntityAction(params);
            return {
                Success: result.Success,
                Message: result.Message,
                ResultData: JSON.stringify(result)
            };
        }
        catch (e) {
            return this.handleError(e);
        }
    }
    getEntityAction(actionID) {
        const entityAction = EntityActionEngineServer.Instance.EntityActions.find(ea => ea.ID === actionID);
        if (!entityAction) {
            throw new Error(`EntityAction with ID ${actionID} not found`);
        }
        return entityAction;
    }
    createBaseParams(entityAction, invocationTypeName, user) {
        return {
            EntityAction: entityAction,
            InvocationType: { Name: invocationTypeName },
            ContextUser: user,
            Params: [],
        };
    }
    async addEntityObject(providers, params, input, user) {
        const md = GetReadOnlyProvider(providers);
        let entity;
        if (input.EntityName) {
            entity = md.Entities.find(e => e.Name === input.EntityName);
            if (!entity) {
                throw new Error(`Entity with name ${input.EntityName} not found`);
            }
        }
        else if (input.EntityID) {
            entity = md.Entities.find(e => e.ID === input.EntityID);
            if (!entity) {
                throw new Error(`Entity with ID ${input.EntityID} not found`);
            }
        }
        if (!entity) {
            throw new Error("Entity information is required");
        }
        const compositeKey = this.createCompositeKey(entity, input.PrimaryKey);
        const entityObject = await md.GetEntityObject(entity.Name);
        await entityObject.InnerLoad(compositeKey);
        params['EntityObject'] = entityObject;
    }
    createCompositeKey(entity, primaryKey) {
        const compositeKey = new CompositeKey();
        for (const kvp of primaryKey.KeyValuePairs) {
            const field = entity.Fields.find(f => f.Name === kvp.Key);
            let value = kvp.Value;
            if (field) {
                value = this.convertValueToProperType(value, field);
            }
            const kvPair = new KeyValuePair();
            kvPair.FieldName = kvp.Key;
            kvPair.Value = value;
            compositeKey.KeyValuePairs.push(kvPair);
        }
        return compositeKey;
    }
    convertValueToProperType(value, field) {
        if (field.Type.toLowerCase().match(/int|decimal|float|money|numeric|real/) && !isNaN(Number(value))) {
            return Number(value);
        }
        else if (field.Type.toLowerCase().includes('date') && !isNaN(Date.parse(value))) {
            return new Date(value);
        }
        return value;
    }
    addOptionalParams(params, input) {
        if (input.ListID) {
            params['ListID'] = input.ListID;
        }
        if (input.ViewID) {
            params['ViewID'] = input.ViewID;
        }
        if (input.Params && input.Params.length > 0) {
            params.Params = input.Params.map(p => this.convertParameterValue(p));
        }
    }
    convertParameterValue(p) {
        let value = p.Value;
        try {
            if (p.Value && (p.Type === 'object' || p.Type === 'array')) {
                value = JSON.parse(p.Value);
            }
        }
        catch (e) {
            const error = e;
            LogError(`Failed to parse parameter value as JSON: ${error.message}`);
        }
        return {
            Name: p.Name,
            Value: value,
            Type: 'Input'
        };
    }
    handleError(e) {
        const error = e;
        LogError(`Error in RunEntityAction resolver: ${error}`);
        return {
            Success: false,
            Message: `Error executing entity action: ${error.message}`
        };
    }
};
__decorate([
    Mutation(() => ActionResultOutput),
    __param(0, Arg("input")),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [RunActionInput, Object]),
    __metadata("design:returntype", Promise)
], ActionResolver.prototype, "RunAction", null);
__decorate([
    Mutation(() => ActionResultOutput),
    __param(0, Arg("input")),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [EntityActionInput, Object]),
    __metadata("design:returntype", Promise)
], ActionResolver.prototype, "RunEntityAction", null);
ActionResolver = __decorate([
    Resolver()
], ActionResolver);
export { ActionResolver };
//# sourceMappingURL=ActionResolver.js.map