var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var _a;
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { getApiFilters, getCountryListForGeocode } from 'src/lib/api/helpers';
import { getFiltersFromUrl, getLocationByAddress, recordAction } from 'src/lib/common/helpers';
import searchApi from 'src/lib/api/services/search';
import log from 'src/lib/api/services/log';
import { PatientType, SFDCPatientType, DocTypeLabel, SortTypesTables, } from 'src/lib/types/types';
import { logTypes, searchSources } from 'src/lib/constants';
import { track } from 'src/lib/common/helpers/tracking';
import { setZipLatLng } from './common';
import { setCache } from './cache';
import { getFiltersCacheId, isCacheExpired } from 'src/lib/common/helpers/cache';
import { setFilters } from './filter';
var cacheHoldTime = process.env.REACT_APP_CACHE_HOLD_TIME_IN_MINS;
export var initialState = {
    result: [],
    isLoading: false,
    error: undefined,
    isDirect: false,
    address: '',
    effectiveRadius: undefined,
    startedAt: undefined,
    hasSearched: false,
};
export var doSearch = createAsyncThunk('search/doSearch', function (props_1, _a) { return __awaiter(void 0, [props_1, _a], void 0, function (props, _b) {
    var _c, filters, _d, language, languageData, stateOptions, enableGoogleSearch, country, countryData, fromMiniSearch, tierPins, cache, common, distUnit, t, zip, state, vivera, patientType, ulat, ulng, uaddress, doctorName, sortType, isOrthoDoc, isGeneralDoc, isPediatric, radius, tier, fservice, flan, fpinsurance, treatments, _e, zlat, zlng, zaddress, hasGeometry, getResults, results;
    var _f, _g;
    var getState = _b.getState, dispatch = _b.dispatch;
    return __generator(this, function (_h) {
        switch (_h.label) {
            case 0:
                _c = getState(), filters = _c.filter.filters, _d = _c.config.config, language = _d.language, languageData = _d.languageData, stateOptions = _d.stateOptions, enableGoogleSearch = _d.enableGoogleSearch, country = _d.country, countryData = _d.countryData, fromMiniSearch = _d.fromMiniSearch, tierPins = _d.tierPins, cache = _c.cache, common = _c.common;
                distUnit = (_g = (_f = countryData[country]) === null || _f === void 0 ? void 0 : _f.shortDistUnit) !== null && _g !== void 0 ? _g : 'mi';
                t = languageData[language];
                zip = filters.zip, state = filters.state, vivera = filters.vivera, patientType = filters.patientType, ulat = filters.lat, ulng = filters.lng, uaddress = filters.address, doctorName = filters.doctorName, sortType = filters.sortType, isOrthoDoc = filters.isOrthoDoc, isGeneralDoc = filters.isGeneralDoc, isPediatric = filters.isPediatric, radius = filters.radius, tier = filters.tier, fservice = filters.fservice, flan = filters.flan, fpinsurance = filters.fpinsurance, treatments = filters.treatments;
                _e = common.zipLatLng, zlat = _e.lat, zlng = _e.lng, zaddress = _e.address;
                hasGeometry = ((ulat && ulng) || uaddress || (zlat && zlng) || zaddress) && uaddress === zaddress;
                if (zip === '' && !((ulat && ulng) || (zlat && zlng)) && !(uaddress || zaddress)) {
                    alert(t.zip_code_empty);
                    return [2 /*return*/, []];
                }
                getResults = function () { return __awaiter(void 0, void 0, void 0, function () {
                    var setUniversalFadSearch, setFromMiniSearch, tierData, cacheId, filtersCache, cacheIsExpired, _a, gaddress, lat, lng, stateOption, stateFullName, address, geocode, _b, address_1, latLng, apiFilters, _c, results, effectiveRadius, getPatientType, getDesignation, treats, treats;
                    var _d, _e, _f, _g, _h;
                    return __generator(this, function (_j) {
                        switch (_j.label) {
                            case 0:
                                setUniversalFadSearch = (_d = props === null || props === void 0 ? void 0 : props.customProps) === null || _d === void 0 ? void 0 : _d.setUniversalFadSearch;
                                setFromMiniSearch = (_e = props === null || props === void 0 ? void 0 : props.customProps) === null || _e === void 0 ? void 0 : _e.setFromMiniSearch;
                                tierData = tierPins.find(function (pins) { return pins.segmentCode === tier; });
                                cacheId = getFiltersCacheId(filters);
                                filtersCache = cache.search && cache.search[cacheId];
                                if (filtersCache) {
                                    cacheIsExpired = isCacheExpired(filtersCache);
                                    if (!cacheIsExpired) {
                                        _a = filtersCache.geocode, gaddress = _a.address, lat = _a.lat, lng = _a.lng;
                                        dispatch(setZipLatLng({ lat: lat, lng: lng, address: gaddress }));
                                        dispatch(setAddress(gaddress));
                                        return [2 /*return*/, filtersCache.cache];
                                    }
                                }
                                stateOption = stateOptions.find(function (st) { return st.value === state; });
                                stateFullName = (stateOption === null || stateOption === void 0 ? void 0 : stateOption.value) ? stateOption.label : '';
                                address = stateFullName || zip || uaddress || zaddress;
                                if (!isNaN(Number(address)) && ((_f = (address || '')) === null || _f === void 0 ? void 0 : _f.length) > 5 && country === 'br')
                                    address = "".concat(address === null || address === void 0 ? void 0 : address.slice(0, 5), "-").concat(address === null || address === void 0 ? void 0 : address.slice(5, address.length));
                                if (!(enableGoogleSearch && hasGeometry)) return [3 /*break*/, 1];
                                _b = {
                                    address: zaddress || uaddress,
                                    lat: Number(ulat || zlat),
                                    lng: Number(ulng || zlng),
                                    message: '',
                                };
                                return [3 /*break*/, 3];
                            case 1: return [4 /*yield*/, getLocationByAddress("".concat(address, ", ").concat(((_g = countryData[country]) === null || _g === void 0 ? void 0 : _g.geoCountry) ||
                                    getCountryListForGeocode(zip || "".concat(address), true)), language.toLowerCase(), country.toLowerCase())];
                            case 2:
                                _b = _j.sent();
                                _j.label = 3;
                            case 3:
                                geocode = _b;
                                if (geocode instanceof Error) {
                                    if (geocode.message.includes('API key')) {
                                        alert(t.something_wrong);
                                    }
                                    else {
                                        log.doLog(logTypes.InvalidAddress, 500, searchSources.DIRECT, 0);
                                        alert(t.unrecognized_zip);
                                    }
                                    // TODO: figure reject
                                    return [2 /*return*/, [{ error: 'zip' }]];
                                }
                                else {
                                    address_1 = geocode.address, latLng = __rest(geocode, ["address"]);
                                    dispatch(setZipLatLng(__assign({ address: address_1 }, latLng)));
                                    dispatch(setAddress(address_1));
                                    if (enableGoogleSearch)
                                        dispatch(setFilters({ address: address_1, zip: '' }));
                                }
                                apiFilters = getApiFilters(__assign(__assign(__assign({}, filters), props === null || props === void 0 ? void 0 : props.customFilters), { latitude: geocode.lat, longitude: geocode.lng }));
                                return [4 /*yield*/, searchApi.doSearch(apiFilters)];
                            case 4:
                                _c = _j.sent(), results = _c.results, effectiveRadius = _c.effectiveRadius;
                                getPatientType = function () {
                                    if (patientType === PatientType.TEEN)
                                        return SFDCPatientType.TEEN;
                                    if (patientType === PatientType.ADULT)
                                        return SFDCPatientType.ADULT;
                                    return SFDCPatientType.PARENT;
                                };
                                getDesignation = function () {
                                    var des = [];
                                    if (isOrthoDoc)
                                        des.push(DocTypeLabel.ORTHO);
                                    if (isGeneralDoc)
                                        des.push(DocTypeLabel.GENERAL);
                                    if (isPediatric)
                                        des.push(DocTypeLabel.PERIATRIC);
                                    return des.join('|');
                                };
                                if (results && results.length > 0) {
                                    effectiveRadius && dispatch(setEffectiveRadius(effectiveRadius));
                                    dispatch(setCache({
                                        key: 'search',
                                        id: cacheId,
                                        cache: results,
                                        geocode: { address: geocode.address, lat: geocode.lat, lng: geocode.lng },
                                    }));
                                    if (((_h = props === null || props === void 0 ? void 0 : props.customProps) === null || _h === void 0 ? void 0 : _h.newSearch) && !setUniversalFadSearch) {
                                        if (!fromMiniSearch) {
                                            treats = [];
                                            if (treatments === null || treatments === void 0 ? void 0 : treatments.itero) {
                                                treats.push('itero');
                                            }
                                            if (treatments === null || treatments === void 0 ? void 0 : treatments.whitening) {
                                                treats.push('WHITENING');
                                            }
                                            if (treatments === null || treatments === void 0 ? void 0 : treatments.vivera_retainers) {
                                                treats.push('Vivera');
                                            }
                                            if (treatments === null || treatments === void 0 ? void 0 : treatments.ipe) {
                                                treats.push('ipe');
                                            }
                                            if (treatments === null || treatments === void 0 ? void 0 : treatments.invisalign_first) {
                                                treats.push('invisalign_first');
                                            }
                                            track('find_a_doctor_zip_entered', {
                                                doc_loc_search_location: 'serp',
                                                zip_code_searched: address || '',
                                                user_category: getPatientType(),
                                                serp_filter_name: doctorName,
                                                serp_filter_sort: SortTypesTables[sortType],
                                                serp_filter_designation: getDesignation(),
                                                serp_filter_distance: "".concat(radius, " ").concat(distUnit),
                                                serp_filter_tier: (tierData === null || tierData === void 0 ? void 0 : tierData.label) || t.no_tier_event_label,
                                                serp_filter_service: fservice.filter(Boolean).join(','),
                                                serp_filter_treatment: treats.join(','),
                                                serp_filter_insurance: fpinsurance.filter(Boolean).join(','),
                                                serp_filter_language: flan.filter(Boolean).join(','),
                                                program: filters.program,
                                            });
                                        }
                                    }
                                    if (setUniversalFadSearch)
                                        setUniversalFadSearch(false);
                                    if (setFromMiniSearch)
                                        setFromMiniSearch(false);
                                    return [2 /*return*/, results];
                                }
                                else {
                                    treats = [];
                                    if (treatments === null || treatments === void 0 ? void 0 : treatments.itero) {
                                        treats.push('itero');
                                    }
                                    if (treatments === null || treatments === void 0 ? void 0 : treatments.whitening) {
                                        treats.push('WHITENING');
                                    }
                                    if (treatments === null || treatments === void 0 ? void 0 : treatments.vivera_retainers) {
                                        treats.push('Vivera');
                                    }
                                    if (treatments === null || treatments === void 0 ? void 0 : treatments.ipe) {
                                        treats.push('ipe');
                                    }
                                    if (treatments === null || treatments === void 0 ? void 0 : treatments.invisalign_first) {
                                        treats.push('invisalign_first');
                                    }
                                    track('find_a_doctor_zip_entered', {
                                        doc_loc_search_location: 'serp',
                                        zip_code_searched: address || '',
                                        user_category: getPatientType(),
                                        serp_filter_name: doctorName,
                                        serp_filter_sort: SortTypesTables[sortType],
                                        serp_filter_designation: getDesignation(),
                                        serp_filter_distance: "".concat(radius, " ").concat(distUnit),
                                        serp_filter_tier: (tierData === null || tierData === void 0 ? void 0 : tierData.label) || t.no_tier_event_label,
                                        serp_filter_service: fservice.filter(Boolean).join(','),
                                        serp_filter_treatment: treats.join(','),
                                        serp_filter_insurance: fpinsurance.filter(Boolean).join(','),
                                        serp_filter_language: flan.filter(Boolean).join(','),
                                        doc_loc_search_results: 0,
                                        program: filters.program,
                                    });
                                }
                                return [2 /*return*/, [{ error: 'zip' }]];
                        }
                    });
                }); };
                return [4 /*yield*/, getResults()];
            case 1:
                results = _h.sent();
                results.length > 0 && !isErrorResult(results) && (props === null || props === void 0 ? void 0 : props.callback) && props.callback();
                recordAction('bt');
                return [2 /*return*/, results];
        }
    });
}); });
export var searchSlice = createSlice({
    name: 'search',
    initialState: initialState,
    reducers: {
        setAddress: function (state, action) {
            state.address = action.payload;
        },
        setEffectiveRadius: function (state, action) {
            state.effectiveRadius = action.payload;
        },
        setIsDirect: function (state, action) {
            state.isDirect = action.payload;
        },
        setStartedAt: function (state, action) {
            state.startedAt = action.payload;
        },
    },
    extraReducers: function (builder) {
        builder
            .addCase(doSearch.pending, function (state) {
            var date = new Date();
            state.isLoading = true;
            state.hasSearched = true;
            state.startedAt = "".concat(date.getFullYear(), "-").concat(date.getMonth() + 1, "-").concat(date.getDate(), " ").concat(date.getHours(), ":").concat(date.getMinutes(), ":").concat(date.getSeconds());
        })
            .addCase(doSearch.fulfilled, function (state, action) {
            var _a = getFiltersFromUrl(), zip = _a.zip, lat = _a.lat, lng = _a.lng, address = _a.address;
            var isError = isErrorResult(action.payload);
            var result = !isError ? action.payload : [];
            var isLoading = isError ? false : !(zip || (lat && lng) || address);
            state.result = result;
            state.isLoading = isLoading;
            state.error = undefined;
        })
            .addCase(doSearch.rejected, function (state, action) {
            state.isLoading = false;
            state.error = action.error;
        });
    },
});
var isErrorResult = function (result) { var _a; return (_a = result[0]) === null || _a === void 0 ? void 0 : _a.error; };
export var setAddress = (_a = searchSlice.actions, _a.setAddress), setIsDirect = _a.setIsDirect, setStartedAt = _a.setStartedAt, setEffectiveRadius = _a.setEffectiveRadius;
export default searchSlice.reducer;
