import { nanoid } from 'nanoid';
import { InvitationKind } from '../kinds.js';
import { Builder } from '@api-client/json/patch/builder.js';
/**
 * Represents an invitation to join an organization.
 * This class implements the `InvitationSchema` interface and provides methods to create and manipulate invitations.
 */
export class Invitation {
    kind;
    key;
    uid;
    oid;
    email;
    name;
    token;
    expiresAt;
    respondedAt;
    status;
    grantType;
    deleted;
    deletedInfo;
    createdAt;
    updatedAt;
    resent;
    lastSentAt;
    #builder;
    /**
     * The patch builder for this invitation.
     */
    get builder() {
        if (!this.#builder) {
            this.#builder = new Builder(this.toJSON());
        }
        return this.#builder;
    }
    /**
     * Creates a full invitation schema with defaults.
     *
     * @param input The partial invitation schema.
     * @returns The invitation schema.
     */
    static createSchema(input = {}) {
        const { key = nanoid(), email, oid, grantType, uid = '', updatedAt = 0, createdAt = 0, expiresAt = 0, resent = 0, lastSentAt = 0, status = 'pending', token = '', } = input;
        if (!email) {
            throw new Error('Email is required to create an invitation schema.');
        }
        if (!oid) {
            throw new Error('Organization ID is required to create an invitation schema.');
        }
        if (!grantType) {
            throw new Error('Grant type is required to create an invitation schema.');
        }
        const result = {
            kind: InvitationKind,
            key,
            uid,
            oid,
            email,
            grantType,
            token,
            expiresAt,
            status,
            createdAt,
            updatedAt,
            resent,
            lastSentAt,
        };
        if (input.name) {
            result.name = input.name;
        }
        if (input.token) {
            result.token = input.token;
        }
        if (input.expiresAt) {
            result.expiresAt = input.expiresAt;
        }
        if (input.respondedAt) {
            result.respondedAt = input.respondedAt;
        }
        if (input.status) {
            result.status = input.status;
        }
        if (input.deleted) {
            result.deleted = input.deleted;
            result.deletedInfo = input.deletedInfo;
        }
        return result;
    }
    constructor(input) {
        const init = Invitation.createSchema(input);
        this.kind = InvitationKind;
        this.key = init.key;
        this.uid = init.uid;
        this.oid = init.oid;
        this.email = init.email;
        this.name = init.name;
        this.token = init.token;
        this.expiresAt = init.expiresAt;
        this.respondedAt = init.respondedAt;
        this.status = init.status;
        this.grantType = init.grantType;
        this.deleted = init.deleted || false;
        this.deletedInfo = init.deletedInfo;
        this.createdAt = init.createdAt;
        this.updatedAt = init.updatedAt;
        this.resent = init.resent;
        this.lastSentAt = init.lastSentAt;
    }
    toJSON() {
        const result = {
            kind: this.kind,
            key: this.key,
            uid: this.uid,
            oid: this.oid,
            email: this.email,
            token: this.token,
            expiresAt: this.expiresAt,
            status: this.status,
            grantType: this.grantType,
            deleted: this.deleted,
            createdAt: this.createdAt,
            updatedAt: this.updatedAt,
            resent: this.resent,
            lastSentAt: this.lastSentAt,
        };
        if (this.name) {
            result.name = this.name;
        }
        if (this.respondedAt) {
            result.respondedAt = this.respondedAt;
        }
        if (this.deletedInfo) {
            result.deletedInfo = { ...this.deletedInfo };
        }
        return result;
    }
    /**
     * Retrieves the patch operations for this invitation.
     * This method builds a JSON Patch representation of the invitation,
     * which can be used to update the invitation in a database or API.
     *
     * Use one of the `set*` methods to modify the invitation before calling this method.
     *
     * @returns An array of patch operations.
     * If no changes have been made, it returns an empty array.
     */
    getPatch() {
        if (!this.#builder) {
            return [];
        }
        return this.builder.build();
    }
    /**
     * Sets the name of the user to whom the invitation is sent.
     * If the name is the same as the current name, no operation is performed.
     *
     * @param name The name to set. If undefined, it will be removed.
     */
    setName(name) {
        if (name === this.name) {
            return;
        }
        const hasName = !!this.name;
        if (hasName && !name) {
            this.builder.remove('/name');
        }
        else {
            // The add method handles both adding and replacing
            this.builder.add('/name', name);
        }
        this.name = name;
    }
    /**
     * Sets the expiration timestamp of the invitation.
     * @param expiresAt The timestamp when the invitation expires.
     * If the expiresAt is the same as the current expiresAt, no operation is performed.
     */
    setExpiresAt(expiresAt) {
        if (this.expiresAt !== expiresAt) {
            this.builder.replace('/expiresAt', expiresAt);
            this.expiresAt = expiresAt;
        }
    }
    /**
     * Sets the grant type of the user in the organization.
     */
    setGrantType(grantType) {
        if (this.grantType !== grantType) {
            this.builder.replace('/grantType', grantType);
            this.grantType = grantType;
        }
    }
}
//# sourceMappingURL=Invitation.js.map