/*!
 * Built by ShiftSoftware
 * Copyright (c)
 */
import { smartInvokable } from "../blazor-ref/index";
import { vehicleRequestHeaders } from "./types";
import validateVin from "../../global/lib/validate-vin";
export const setVehicleLookupData = async (context, newData, headers = {}, { beforeAssignment } = {}) => {
    var _a;
    if (newData === null || newData === undefined)
        newData = ((_a = context.vehicleLookup) === null || _a === void 0 ? void 0 : _a.vin) || '';
    // clears network timeoutRef which serves as await for animation
    clearTimeout(context.networkTimeoutRef);
    // handles request spam by canceling the previous ones
    if (context.abortController)
        context.abortController.abort();
    context.abortController = new AbortController();
    // syncing the internal timeout ref with external network ref
    let scopedTimeoutRef;
    const isVinRequest = typeof newData === 'string';
    const vin = typeof newData === 'string' ? newData : newData === null || newData === void 0 ? void 0 : newData.vin;
    try {
        context.isLoading = true;
        await new Promise(r => {
            scopedTimeoutRef = setTimeout(r, 1000);
            context.networkTimeoutRef = scopedTimeoutRef;
        });
        if ((!vin || vin.trim().length === 0) && !(context === null || context === void 0 ? void 0 : context.isDev)) {
            context.isError = false;
            context.isLoading = false;
            context.vehicleLookup = undefined;
            throw new Error('vinNumberRequired');
        }
        if (!validateVin(vin) && !(context === null || context === void 0 ? void 0 : context.isDev) && !(context === null || context === void 0 ? void 0 : context.disableVinValidation))
            throw new Error('invalidVin');
        const vehicleResponse = isVinRequest ? await getVehicleLookup(context, { scopedTimeoutRef, vin }, headers) : newData;
        if (context.networkTimeoutRef === scopedTimeoutRef) {
            if (!vehicleResponse)
                throw new Error('wrongResponseFormat');
            if (beforeAssignment)
                context.vehicleLookup = await beforeAssignment(vehicleResponse, { scopedTimeoutRef });
            else
                context.vehicleLookup = vehicleResponse;
            // Fire loadedResponse after vehicleLookup is set to ensure consistent state
            // Only for VIN requests — DTO distribution should not re-trigger the callback chain
            if (isVinRequest) {
                smartInvokable.bind(context)(context === null || context === void 0 ? void 0 : context.loadedResponse, vehicleResponse);
            }
        }
        context.errorMessage = null;
        context.isLoading = false;
        context.isError = false;
    }
    catch (error) {
        if (error && (error === null || error === void 0 ? void 0 : error.name) === 'AbortError')
            return;
        smartInvokable.bind(context)(context === null || context === void 0 ? void 0 : context.errorCallback, error.message);
        console.error(error);
        context.setErrorMessage(error.message);
        context.isLoading = false;
    }
};
export const setVehicleLookupErrorState = (context, message) => {
    context.isError = true;
    context.isLoading = false;
    context.errorMessage = message;
    context.vehicleLookup = undefined;
};
export const getVehicleLookup = async (context, generalProps, headers = {}) => {
    const { vin, scopedTimeoutRef } = generalProps;
    const handleResult = (newVehicleInformation) => {
        if ((context === null || context === void 0 ? void 0 : context.networkTimeoutRef) === scopedTimeoutRef) {
            if (!newVehicleInformation && vin)
                throw new Error('wrongResponseFormat');
            return newVehicleInformation;
        }
    };
    if (context === null || context === void 0 ? void 0 : context.isDev) {
        const newData = context === null || context === void 0 ? void 0 : context.mockData[vin];
        return handleResult(newData);
    }
    else {
        if (!(context === null || context === void 0 ? void 0 : context.baseUrl))
            throw new Error('noBaseUrl');
        const componentHeaders = Object.assign({}, headers);
        Object.entries(vehicleRequestHeaders).forEach(([componentHeaderKey, headerField]) => {
            if (context[componentHeaderKey])
                componentHeaders[headerField] = context[componentHeaderKey];
        });
        const response = await fetch(`${context === null || context === void 0 ? void 0 : context.baseUrl}${vin}?${context === null || context === void 0 ? void 0 : context.queryString}`, { signal: context === null || context === void 0 ? void 0 : context.abortController.signal, headers: componentHeaders });
        const newData = (await response.json());
        return handleResult(newData);
    }
};
