"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlackbaudSkyApi = void 0;
const actions_core_1 = require("@segment/actions-core");
const constants_1 = require("../constants");
const utils_1 = require("../utils");
class BlackbaudSkyApi {
    constructor(request) {
        this.request = request;
    }
    async searchForConstituents(searchField, searchText) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/constituents/search?search_field=${searchField}&search_text=${searchText}`, {
            method: 'get'
        });
    }
    async getExistingConstituent(emailData, lookupId) {
        let constituentId = undefined;
        let searchField = 'email_address';
        let searchText = emailData?.address || '';
        if (lookupId) {
            searchField = 'lookup_id';
            searchText = lookupId;
        }
        const constituentSearchResponse = await this.searchForConstituents(searchField, searchText);
        const constituentSearchResults = await constituentSearchResponse.json();
        if (constituentSearchResults.count > 1) {
            throw new actions_core_1.IntegrationError('Multiple records returned for given traits', 'MULTIPLE_EXISTING_RECORDS', 400);
        }
        else if (constituentSearchResults.count === 1) {
            constituentId = constituentSearchResults.value[0].id;
        }
        else if (constituentSearchResults.count !== 0) {
            throw new actions_core_1.IntegrationError('Unexpected constituent record count for given traits', 'UNEXPECTED_RECORD_COUNT', 500);
        }
        return Promise.resolve({
            id: constituentId
        });
    }
    async createConstituent(constituentData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/constituents`, {
            method: 'post',
            json: constituentData
        });
    }
    async createConstituentWithRelatedObjects(constituentData, addressData, emailData, onlinePresenceData, phoneData) {
        constituentData.type = 'Individual';
        if (!constituentData.last) {
            throw new actions_core_1.IntegrationError('Missing last name value', 'MISSING_REQUIRED_FIELD', 400);
        }
        if (Object.keys(addressData).length > 0) {
            constituentData.address = addressData;
        }
        if (Object.keys(emailData).length > 0) {
            constituentData.email = emailData;
        }
        if (Object.keys(onlinePresenceData).length > 0) {
            constituentData.online_presence = onlinePresenceData;
        }
        if (Object.keys(phoneData).length > 0) {
            constituentData.phone = phoneData;
        }
        const createConstituentResponse = await this.createConstituent(constituentData);
        const constituentResult = await createConstituentResponse.json();
        return Promise.resolve({
            id: constituentResult.id
        });
    }
    async updateConstituent(constituentId, constituentData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/constituents/${constituentId}`, {
            method: 'patch',
            json: constituentData,
            throwHttpErrors: false
        });
    }
    async getConstituentAddressList(constituentId) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/constituents/${constituentId}/addresses?include_inactive=true`, {
            method: 'get',
            throwHttpErrors: false
        });
    }
    async createConstituentAddress(constituentId, addressData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/addresses`, {
            method: 'post',
            json: {
                ...addressData,
                constituent_id: constituentId
            },
            throwHttpErrors: false
        });
    }
    async updateConstituentAddressById(addressId, addressData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/addresses/${addressId}`, {
            method: 'patch',
            json: {
                ...addressData,
                inactive: false
            },
            throwHttpErrors: false
        });
    }
    async getConstituentEmailList(constituentId) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/constituents/${constituentId}/emailaddresses?include_inactive=true`, {
            method: 'get',
            throwHttpErrors: false
        });
    }
    async createConstituentEmail(constituentId, emailData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/emailaddresses`, {
            method: 'post',
            json: {
                ...emailData,
                constituent_id: constituentId
            },
            throwHttpErrors: false
        });
    }
    async updateConstituentEmailById(emailId, emailData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/emailaddresses/${emailId}`, {
            method: 'patch',
            json: {
                ...emailData,
                inactive: false
            },
            throwHttpErrors: false
        });
    }
    async getConstituentOnlinePresenceList(constituentId) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/constituents/${constituentId}/onlinepresences?include_inactive=true`, {
            method: 'get',
            throwHttpErrors: false
        });
    }
    async createConstituentOnlinePresence(constituentId, onlinePresenceData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/onlinepresences`, {
            method: 'post',
            json: {
                ...onlinePresenceData,
                constituent_id: constituentId
            },
            throwHttpErrors: false
        });
    }
    async updateConstituentOnlinePresenceById(onlinePresenceId, onlinePresenceData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/onlinepresences/${onlinePresenceId}`, {
            method: 'patch',
            json: {
                ...onlinePresenceData,
                inactive: false
            },
            throwHttpErrors: false
        });
    }
    async getConstituentPhoneList(constituentId) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/constituents/${constituentId}/phones?include_inactive=true`, {
            method: 'get',
            throwHttpErrors: false
        });
    }
    async createConstituentPhone(constituentId, phoneData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/phones`, {
            method: 'post',
            json: {
                ...phoneData,
                constituent_id: constituentId
            },
            throwHttpErrors: false
        });
    }
    async updateConstituentWithRelatedObjects(constituentId, constituentData, addressData, emailData, onlinePresenceData, phoneData) {
        const integrationErrors = [];
        if (Object.keys(constituentData).length > 0) {
            const updateConstituentResponse = await this.updateConstituent(constituentId, constituentData);
            if (updateConstituentResponse.status !== 200) {
                const statusCode = updateConstituentResponse.status;
                const errorMessage = statusCode
                    ? `${statusCode} error occurred when updating constituent`
                    : 'Error occurred when updating constituent';
                if ((0, utils_1.isRequestErrorRetryable)(statusCode)) {
                    throw new actions_core_1.RetryableError(errorMessage);
                }
                else {
                    integrationErrors.push(errorMessage);
                }
            }
        }
        if (Object.keys(addressData).length > 0) {
            const getConstituentAddressListResponse = await this.getConstituentAddressList(constituentId);
            let updateAddressErrorCode = undefined;
            if (getConstituentAddressListResponse.status !== 200) {
                updateAddressErrorCode = getConstituentAddressListResponse.status;
            }
            else {
                const constituentAddressListResults = await getConstituentAddressListResponse.json();
                let existingAddress = undefined;
                if (constituentAddressListResults.count > 0) {
                    existingAddress = (0, utils_1.filterObjectListByMatchFields)(constituentAddressListResults.value, addressData, [
                        'address_lines',
                        'city',
                        'postal_code',
                        'state'
                    ]);
                }
                if (!existingAddress) {
                    if (addressData.primary !== false && constituentAddressListResults.count === 0) {
                        addressData.primary = true;
                    }
                    const createConstituentAddressResponse = await this.createConstituentAddress(constituentId, addressData);
                    if (createConstituentAddressResponse.status !== 200) {
                        updateAddressErrorCode = createConstituentAddressResponse.status;
                    }
                }
                else {
                    if (existingAddress.inactive ||
                        (addressData.do_not_mail !== undefined && addressData.do_not_mail !== existingAddress.do_not_mail) ||
                        (addressData.primary !== undefined &&
                            addressData.primary &&
                            addressData.primary !== existingAddress.primary) ||
                        addressData.type !== existingAddress.type) {
                        const updateConstituentAddressByIdResponse = await this.updateConstituentAddressById(existingAddress.id, addressData);
                        if (updateConstituentAddressByIdResponse.status !== 200) {
                            updateAddressErrorCode = updateConstituentAddressByIdResponse.status;
                        }
                    }
                }
            }
            if (updateAddressErrorCode) {
                const errorMessage = updateAddressErrorCode
                    ? `${updateAddressErrorCode} error occurred when updating constituent address`
                    : 'Error occurred when updating constituent address';
                if ((0, utils_1.isRequestErrorRetryable)(updateAddressErrorCode)) {
                    throw new actions_core_1.RetryableError(errorMessage);
                }
                else {
                    integrationErrors.push(errorMessage);
                }
            }
        }
        if (Object.keys(emailData).length > 0) {
            const getConstituentEmailListResponse = await this.getConstituentEmailList(constituentId);
            let updateEmailErrorCode = undefined;
            if (getConstituentEmailListResponse.status !== 200) {
                updateEmailErrorCode = getConstituentEmailListResponse.status;
            }
            else {
                const constituentEmailListResults = await getConstituentEmailListResponse.json();
                let existingEmail = undefined;
                if (constituentEmailListResults.count > 0) {
                    existingEmail = (0, utils_1.filterObjectListByMatchFields)(constituentEmailListResults.value, emailData, ['address']);
                }
                if (!existingEmail) {
                    if (emailData.primary !== false && constituentEmailListResults.count === 0) {
                        emailData.primary = true;
                    }
                    const createConstituentEmailResponse = await this.createConstituentEmail(constituentId, emailData);
                    if (createConstituentEmailResponse.status !== 200) {
                        updateEmailErrorCode = createConstituentEmailResponse.status;
                    }
                }
                else {
                    if (existingEmail.inactive ||
                        (emailData.do_not_email !== undefined && emailData.do_not_email !== existingEmail.do_not_email) ||
                        (emailData.primary !== undefined && emailData.primary && emailData.primary !== existingEmail.primary) ||
                        emailData.type !== existingEmail.type) {
                        const updateConstituentEmailByIdResponse = await this.updateConstituentEmailById(existingEmail.id, emailData);
                        if (updateConstituentEmailByIdResponse.status !== 200) {
                            updateEmailErrorCode = updateConstituentEmailByIdResponse.status;
                        }
                    }
                }
            }
            if (updateEmailErrorCode) {
                const errorMessage = updateEmailErrorCode
                    ? `${updateEmailErrorCode} error occurred when updating constituent email`
                    : 'Error occurred when updating constituent email';
                if ((0, utils_1.isRequestErrorRetryable)(updateEmailErrorCode)) {
                    throw new actions_core_1.RetryableError(errorMessage);
                }
                else {
                    integrationErrors.push(errorMessage);
                }
            }
        }
        if (Object.keys(onlinePresenceData).length > 0) {
            const getConstituentOnlinePresenceListResponse = await this.getConstituentOnlinePresenceList(constituentId);
            let updateOnlinePresenceErrorCode = undefined;
            if (getConstituentOnlinePresenceListResponse.status !== 200) {
                updateOnlinePresenceErrorCode = getConstituentOnlinePresenceListResponse.status;
            }
            else {
                const constituentOnlinePresenceListResults = await getConstituentOnlinePresenceListResponse.json();
                let existingOnlinePresence = undefined;
                if (constituentOnlinePresenceListResults.count > 0) {
                    existingOnlinePresence = (0, utils_1.filterObjectListByMatchFields)(constituentOnlinePresenceListResults.value, onlinePresenceData, ['address']);
                }
                if (!existingOnlinePresence) {
                    if (onlinePresenceData.primary !== false && constituentOnlinePresenceListResults.count === 0) {
                        onlinePresenceData.primary = true;
                    }
                    const createConstituentOnlinePresenceResponse = await this.createConstituentOnlinePresence(constituentId, onlinePresenceData);
                    if (createConstituentOnlinePresenceResponse.status !== 200) {
                        updateOnlinePresenceErrorCode = createConstituentOnlinePresenceResponse.status;
                    }
                }
                else {
                    if (existingOnlinePresence.inactive ||
                        (onlinePresenceData.primary !== undefined &&
                            onlinePresenceData.primary !== existingOnlinePresence.primary) ||
                        onlinePresenceData.type !== existingOnlinePresence.type) {
                        const updateConstituentOnlinePresenceByIdResponse = await this.updateConstituentOnlinePresenceById(existingOnlinePresence.id, onlinePresenceData);
                        if (updateConstituentOnlinePresenceByIdResponse.status !== 200) {
                            updateOnlinePresenceErrorCode = updateConstituentOnlinePresenceByIdResponse.status;
                        }
                    }
                }
            }
            if (updateOnlinePresenceErrorCode) {
                const errorMessage = updateOnlinePresenceErrorCode
                    ? `${updateOnlinePresenceErrorCode} error occurred when updating constituent online presence`
                    : 'Error occurred when updating constituent online presence';
                if ((0, utils_1.isRequestErrorRetryable)(updateOnlinePresenceErrorCode)) {
                    throw new actions_core_1.RetryableError(errorMessage);
                }
                else {
                    integrationErrors.push(errorMessage);
                }
            }
        }
        if (Object.keys(phoneData).length > 0) {
            const getConstituentPhoneListResponse = await this.getConstituentPhoneList(constituentId);
            let updatePhoneErrorCode = undefined;
            if (getConstituentPhoneListResponse.status !== 200) {
                updatePhoneErrorCode = getConstituentPhoneListResponse.status;
            }
            else {
                const constituentPhoneListResults = await getConstituentPhoneListResponse.json();
                let existingPhone = undefined;
                if (constituentPhoneListResults.count > 0) {
                    existingPhone = (0, utils_1.filterObjectListByMatchFields)(constituentPhoneListResults.value, phoneData, [
                        'int:number'
                    ]);
                }
                if (!existingPhone) {
                    if (phoneData.primary !== false && constituentPhoneListResults.count === 0) {
                        phoneData.primary = true;
                    }
                    const createConstituentPhoneResponse = await this.createConstituentPhone(constituentId, phoneData);
                    if (createConstituentPhoneResponse.status !== 200) {
                        updatePhoneErrorCode = createConstituentPhoneResponse.status;
                    }
                }
                else {
                    if (existingPhone.inactive ||
                        (phoneData.do_not_call !== undefined && phoneData.do_not_call !== existingPhone.do_not_call) ||
                        (phoneData.primary !== undefined && phoneData.primary !== existingPhone.primary) ||
                        phoneData.type !== existingPhone.type) {
                        const updateConstituentPhoneByIdResponse = await this.updateConstituentPhoneById(existingPhone.id, phoneData);
                        if (updateConstituentPhoneByIdResponse.status !== 200) {
                            updatePhoneErrorCode = updateConstituentPhoneByIdResponse.status;
                        }
                    }
                }
            }
            if (updatePhoneErrorCode) {
                const errorMessage = updatePhoneErrorCode
                    ? `${updatePhoneErrorCode} error occurred when updating constituent online presence`
                    : 'Error occurred when updating constituent online presence';
                if ((0, utils_1.isRequestErrorRetryable)(updatePhoneErrorCode)) {
                    throw new actions_core_1.RetryableError(errorMessage);
                }
                else {
                    integrationErrors.push(errorMessage);
                }
            }
        }
        if (integrationErrors.length > 0) {
            throw new actions_core_1.IntegrationError('One or more errors occurred when updating existing constituent: ' + integrationErrors.join(', '), 'UPDATE_CONSTITUENT_ERROR', 500);
        }
        return Promise.resolve({
            id: constituentId
        });
    }
    async updateConstituentPhoneById(phoneId, phoneData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/phones/${phoneId}`, {
            method: 'patch',
            json: {
                ...phoneData,
                inactive: false
            },
            throwHttpErrors: false
        });
    }
    async createGift(giftData) {
        return this.request(`${constants_1.SKY_API_GIFTS_URL}/gifts`, {
            method: 'post',
            json: giftData
        });
    }
    async createConstituentAction(constituentActionData) {
        return this.request(`${constants_1.SKY_API_CONSTITUENT_URL}/actions`, {
            method: 'post',
            json: constituentActionData
        });
    }
}
exports.BlackbaudSkyApi = BlackbaudSkyApi;
//# sourceMappingURL=index.js.map