UNPKG

@salla.sa/twilight-components

Version:
2,371 lines 118 kB
/*!
 * Crafted with ❤ by Salla
 */
import { h, Host, } from "@stencil/core";
import { bulletDeliveryAPI, clearApiCache, isSaudiArabia } from "./api-service";
import { buildAddressLocationPayloadFromSelection, filterBranches, findNearestBranch, formatWorkingHoursDisplay, getBranchFirstSlot, getGeolocationErrorMessage, getIntentBranchId, getIntentCityId, getIntentCountryCode, getIntentCountryId, getIntentDistrictId, getIntentLatitude, getIntentLongitude, getIntentRegionId, getIntentSubtitle, hasSessionAddressIntent, requireRegionAndDistrictForSA, } from "./helpers";
const BRANCH_SEARCH_DEBOUNCE_MS = 1000;
const GEOLOCATION_TIMEOUT = 10000;
import GetDirections from "../../assets/svg/get-directions.svg";
import GPS from "../../assets/svg/gps.svg";
import ArrowLeft from "../../assets/svg/keyboard_arrow_left.svg";
import ArrowRight from "../../assets/svg/keyboard_arrow_right.svg";
import Location from "../../assets/svg/location.svg";
import MiniMap from "../../assets/svg/mini-map.svg";
import Search from "../../assets/svg/search.svg";
import Store from "../../assets/svg/store3.svg";
const DEBUG_KEY = 'salla-bullet-delivery-debug';
const OVERRIDE_IP_KEY = 'salla-bullet-delivery-override-ip';
function log(message, data) {
    if (localStorage.getItem(DEBUG_KEY)) {
        data !== undefined ? console.log(message, data) : console.log(message);
    }
}
/**
 * @slot footer - The bottom section of the component for custom actions.
 */
export class SallaBulletDelivery {
    constructor() {
        this.confirming = false;
        this.pendingCartSubmitResolver = null;
        this.pendingCartSubmitPromise = null;
        this.cartSubmitConfirmationPending = false;
        this.branchSearchDebounceTimer = null;
        this.countrySearchTimer = null;
        this.regionSearchTimer = null;
        this.citySearchTimer = null;
        this.districtSearchTimer = null;
        this.citySearchCounter = 0;
        this.componentReady = false;
        this.pendingOpen = false;
        this.tabChanging = false;
        this.intentStorageKey = "bullet_delivery_intent";
        this.sessionShownKey = "bullet_delivery_shown";
        this.incompleteIntentPromptKey = "bullet_delivery_incomplete_intent_prompted";
        this.cartItemAddedEvent = "cart::item.added";
        this.cartItemAddedHandler = null;
        this.cartSubmittingHandler = null;
        this.useCartEventApi = false;
        this.authLoggedInHandler = null;
        this.authLoggedOutHandler = null;
        this.loginClosedHandler = null;
        this.hasExplicitPreselectedIdsForOpen = false;
        this.bulletDeliveryOpenHandler = (eventData) => {
            this.preselectedAddressId = eventData?.preselected_address_id;
            this.preselectedBranchId = eventData?.preselected_branch_id;
            this.hasExplicitPreselectedIdsForOpen =
                eventData?.preselected_address_id != null ||
                    eventData?.preselected_branch_id != null;
            this.open();
        };
        this.closeHandler = null;
        this.bulletDeliveryMobileSelectHandler = null;
        /** True after saved addresses have been loaded (lazy: only when address tab is shown). */
        this.savedAddressesLoaded = false;
        // Core state
        this.activeTab = "address";
        this.isLoggedIn = false;
        this.viewMode = "main";
        // Location data
        this.countries = [];
        this.regions = [];
        this.cities = [];
        this.districts = [];
        this.loadingRegions = false;
        this.selectedCountry = null;
        this.selectedRegion = null;
        this.selectedCity = null;
        this.selectedDistrict = null;
        this.districtName = "";
        // Saved addresses state
        this.savedAddresses = [];
        this.selectedSavedAddress = null;
        /** True when user selected the session address (guest address from before login, not yet saved) */
        this.selectedSessionAddress = false;
        // Pickup state
        this.branches = [];
        this.filteredBranches = [];
        this.selectedBranch = null;
        this.branchSearchQuery = "";
        // Loading states
        this.loadingCountries = false;
        this.loadingCities = false;
        this.loadingDistricts = false;
        this.loadingBranches = false;
        this.loadingNearestBranch = false;
        this.locationError = "";
        this.savingAddress = false;
        this.loadingSavedAddresses = false;
        this.showCartWillBeClearedBanner = false;
        // Searchable dropdown state
        this.countrySearchQuery = '';
        this.regionSearchQuery = '';
        this.citySearchQuery = '';
        this.districtSearchQuery = '';
        this.searchingCountries = false;
        this.searchingRegions = false;
        this.searchingCities = false;
        this.searchingDistricts = false;
        this.displayedCountries = [];
        this.displayedRegions = [];
        this.displayedCities = [];
        this.displayedDistricts = [];
        /** Shown when scopes/allocation returns 422 (address outside delivery coverage). Only on delivery tab. */
        this.allocationOutOfCoverageMessage = null;
        this.newAddressForm = {
            ...SallaBulletDelivery.INITIAL_ADDRESS_FORM,
        };
        this.handleCountrySearch = (query) => {
            this.countrySearchQuery = query;
            return;
        };
        this.handleRegionSearch = (query) => {
            this.regionSearchQuery = query;
            return;
        };
        this.handleCitySearch = (query) => {
            this.citySearchQuery = query;
            if (this.citySearchTimer)
                clearTimeout(this.citySearchTimer);
            if (!query.trim()) {
                this.displayedCities = this.cities;
                this.searchingCities = false;
                return;
            }
            if (query.trim().length < SallaBulletDelivery.DROPDOWN_SEARCH_MIN_CHARS)
                return;
            const requestId = ++this.citySearchCounter;
            this.citySearchTimer = setTimeout(async () => {
                this.searchingCities = true;
                try {
                    const isSA = isSaudiArabia(this.selectedCountry?.code ?? '');
                    const regionId = isSA ? this.selectedRegion?.id : undefined;
                    const results = await bulletDeliveryAPI.getCities(this.selectedCountry?.id, regionId, query);
                    if (requestId === this.citySearchCounter) {
                        this.displayedCities = results;
                    }
                }
                catch {
                    if (requestId === this.citySearchCounter) {
                        this.displayedCities = this.cities;
                    }
                }
                finally {
                    if (requestId === this.citySearchCounter) {
                        this.searchingCities = false;
                    }
                }
            }, SallaBulletDelivery.DROPDOWN_SEARCH_DEBOUNCE_MS);
        };
        this.handleDistrictSearch = (query) => {
            this.districtSearchQuery = query;
            return;
        };
        this.handleCountryDropdownClosed = () => {
            this.countrySearchQuery = '';
            this.displayedCountries = this.countries;
            this.searchingCountries = false;
        };
        this.handleRegionDropdownClosed = () => {
            this.regionSearchQuery = '';
            this.displayedRegions = this.regions;
            this.searchingRegions = false;
        };
        this.handleCityDropdownClosed = () => {
            this.citySearchQuery = '';
            if (this.citySearchTimer) {
                clearTimeout(this.citySearchTimer);
                this.citySearchTimer = null;
            }
            ++this.citySearchCounter;
            this.displayedCities = this.cities;
            this.searchingCities = false;
        };
        this.handleDistrictDropdownClosed = () => {
            this.districtSearchQuery = '';
            this.displayedDistricts = this.districts;
            this.searchingDistricts = false;
        };
        /**
         * Submit add-address form: create address via API then switch back to list.
         */
        this.handleSubmitAddAddress = async (e) => {
            e.preventDefault();
            if (this.savingAddress)
                return;
            if (!this.selectedCountry || !this.selectedCity)
                return;
            if (!requireRegionAndDistrictForSA(this.selectedCountry?.code, this.selectedRegion?.id, this.selectedDistrict?.id ?? (this.districtName?.trim() || null)))
                return;
            this.savingAddress = true;
            try {
                const payload = this.buildAddressLocationPayload();
                const { success, address } = await bulletDeliveryAPI.saveAddressLocation(payload);
                if (success) {
                    await this.loadSavedAddresses();
                    const latest = address ?? this.savedAddresses[0] ?? null;
                    if (latest?.is_in_coverage) {
                        this.selectedSessionAddress = false;
                        this.selectedSavedAddress = latest;
                    }
                    this.addressCreated.emit({ address: latest });
                    this.viewMode = "main";
                    this.districtName = "";
                }
                else {
                    Salla.notify?.error(Salla.lang.get("common.errors.error_occurred"));
                }
            }
            catch (error) {
                console.error("SallaBulletDelivery: Error saving address", error);
                Salla.notify?.error(Salla.lang.get("common.errors.error_occurred"));
            }
            finally {
                this.savingAddress = false;
            }
        };
        this.handleCountrySelected = (item) => {
            const country = this.countries.find(c => String(c.id) === String(item.id)) || item;
            // Hide empty cart alert (INV-44)
            // const isCountrySwitch =
            // 	this.selectedCountry &&
            // 	country &&
            // 	this.selectedCountry.code !== (country as Country).code;
            // this.showCartWillBeClearedBanner = !!isCountrySwitch;
            this.countrySearchQuery = '';
            this.displayedCountries = this.countries;
            this.applyCountryChange(country || null);
        };
        this.handleRegionSelected = (item) => {
            const region = this.regions.find(r => String(r.id) === String(item.id)) || item;
            this.selectedRegion = region || null;
            this.regionSearchQuery = '';
            this.displayedRegions = this.regions;
            this.updateNewAddressForm({
                region_id: region?.id,
                city_id: undefined,
                district_id: undefined,
                city: undefined,
                district: undefined,
            });
            if (region && this.selectedCountry) {
                this.loadCities(this.selectedCountry.id, region.id);
            }
        };
        this.handleCitySelected = (item) => {
            const isSA = isSaudiArabia(this.selectedCountry?.code ?? '');
            const city = this.cities.find(c => String(c.id) === String(item.id)) || item;
            this.selectedCity = city || null;
            this.selectedDistrict = null;
            this.districtName = "";
            this.citySearchQuery = '';
            this.displayedCities = this.cities;
            if (city) {
                this.updateNewAddressForm({ city: city, district: undefined });
                if (isSA) {
                    this.loadDistricts(city.id);
                }
            }
        };
        this.handleDistrictSelected = (item) => {
            const district = this.districts.find(d => String(d.id) === String(item.id)) || item;
            this.selectedDistrict = district || null;
            this.districtName = "";
            this.districtSearchQuery = '';
            this.displayedDistricts = this.districts;
            if (district) {
                this.updateNewAddressForm({ district });
            }
        };
    }
    /** Whether to show delivery + pickup tabs. From store.shipping.support_pickup */
    get supportsPickup() {
        return Boolean(Salla.config.get("store.shipping.support_pickup")) || Boolean(Salla.config.get("store.support_pickup"));
    }
    /** The modal opening strategy: 'first_visit' | 'on_cart_click' | 'after_add_to_cart' */
    get openingType() {
        return Salla.config.get("store.settings.bullet_delivery.settings.type");
    }
    /** Whether the modal is required (cannot be closed/skipped). From store.settings.bullet_delivery.settings.is_required */
    get isRequired() {
        return !!Salla.config.get("store.settings.bullet_delivery.settings.is_required");
    }
    get isMobileApp() {
        return Salla.config.isMobileApp();
    }
    /**
     * Opens the bullet delivery modal
     */
    async open() {
        // If mobile app, open the sheet
        if (this.isMobileApp) {
            Salla.event.dispatch('salla::bullet-delivery.open-sheet');
            return;
        }
        // If component is not ready yet, mark as pending and return
        if (!this.componentReady || !this.modal) {
            this.pendingOpen = true;
            return;
        }
        // Reset state before opening
        this.resetState();
        // Open modal immediately — fields render right away with inline loading
        this.modal.open();
        Salla.event.dispatch("salla::bullet-delivery.modal.opened");
        try {
            this.isLoggedIn = !this.isGuestUser();
            const savedIntent = this.cleanStaleGuestAddressIdIfNeeded(this.getStoredIntent());
            this.applyPreselectedIdsFromIntent(savedIntent);
            const hasStoredAddressIds = !this.isLoggedIn &&
                savedIntent?.type === "address" &&
                getIntentCountryId(savedIntent) != null &&
                getIntentCityId(savedIntent) != null;
            // Set default tab first so we can lazy-load tab-specific data.
            if (this.supportsPickup &&
                savedIntent?.type &&
                (savedIntent.type === "address" || savedIntent.type === "branch")) {
                this.activeTab = savedIntent.type;
            }
            else {
                this.activeTab = "address";
            }
            // Load countries always; load saved addresses only when address tab is active (lazy tab data).
            if (this.isLoggedIn && this.activeTab === "address") {
                this.loadingSavedAddresses = true;
            }
            await Promise.all([
                this.loadCountries(hasStoredAddressIds),
                this.isLoggedIn && this.activeTab === "address"
                    ? this.loadSavedAddresses().then(() => {
                        this.savedAddressesLoaded = true;
                    }).finally(() => {
                        this.loadingSavedAddresses = false;
                    })
                    : Promise.resolve(),
            ]);
            // Auto-select preselected address if provided
            if (this.isLoggedIn && this.preselectedAddressId) {
                const address = this.savedAddresses.find((a) => a.id === this.preselectedAddressId);
                if (address) {
                    this.selectedSessionAddress = false;
                    this.selectedSavedAddress = address;
                }
            }
            // Load branches only when branch tab is active (lazy tab data)
            // Use lat/lng from session storage if available for more accurate results
            if (this.activeTab === "branch") {
                const intentLat = getIntentLatitude(savedIntent);
                const intentLng = getIntentLongitude(savedIntent);
                if (intentLat != null && intentLng != null) {
                    await this.loadBranchesWithLocation(intentLat, intentLng);
                }
                else {
                    await this.loadBranches();
                }
                // Auto-select preselected branch if provided
                if (this.preselectedBranchId) {
                    const branch = this.branches.find((b) => b.id === this.preselectedBranchId);
                    if (branch) {
                        this.selectedBranch = branch;
                    }
                }
            }
            // Prefill form data from session storage
            await this.prefillFromSessionStorage();
        }
        catch (e) {
            console.error("SallaBulletDelivery: Error loading data", e);
        }
        finally {
            this.overrideScopeSwitchUI();
        }
    }
    /**
     * Closes the bullet delivery modal
     */
    async close() {
        if (this.shouldForceNonClosable() && !this.confirming) {
            return;
        }
        // If submit flow is waiting and user dismissed the modal, release the pending gate.
        if (this.cartSubmitConfirmationPending && !this.confirming) {
            this.resolvePendingCartSubmit();
        }
        this.bulletDeliveryClosed.emit();
        return this.modal?.close();
    }
    resetState() {
        this.viewMode = "main";
        this.selectedCountry = null;
        this.selectedRegion = null;
        this.selectedCity = null;
        this.selectedDistrict = null;
        this.districtName = "";
        this.selectedSavedAddress = null;
        this.selectedSessionAddress = false;
        this.selectedBranch = null;
        this.branchSearchQuery = "";
        this.regions = [];
        this.cities = [];
        this.districts = [];
        this.branches = [];
        this.filteredBranches = [];
        this.newAddressForm = { ...SallaBulletDelivery.INITIAL_ADDRESS_FORM };
        this.showCartWillBeClearedBanner = false;
        this.allocationOutOfCoverageMessage = null;
        this.locationError = "";
        this.savedAddressesLoaded = false;
        this.loadingSavedAddresses = false;
        this.loadingCountries = false;
        this.resetSearchState();
    }
    getIntentStorage() {
        const rememberLastSession = Boolean(Salla.config.get("store.settings.bullet_delivery.settings.remember_last_session"));
        return Salla.storage[rememberLastSession ? "store" : "session"];
    }
    getShownStorage() {
        // Always session-scoped. `remember_last_session` applies to intent persistence only.
        return Salla.storage.session;
    }
    getStoredIntent() {
        return this.getIntentStorage().get(this.intentStorageKey);
    }
    isGuestUser() {
        return String(Salla.config.get("user.type") ?? "guest") === "guest";
    }
    cleanStaleGuestAddressIdIfNeeded(intent) {
        if (!this.isGuestUser() || intent?.type !== "address" || !intent.address_id)
            return intent;
        const cleaned = {
            ...intent,
            address_id: undefined,
        };
        this.setStoredIntent(cleaned);
        return cleaned;
    }
    applyPreselectedIdsFromIntent(intent) {
        if (this.hasExplicitPreselectedIdsForOpen) {
            this.hasExplicitPreselectedIdsForOpen = false;
            return;
        }
        this.preselectedAddressId = undefined;
        this.preselectedBranchId = undefined;
        if (this.isGuestUser()) {
            if (intent?.type === "branch" && intent.branch_id) {
                this.preselectedBranchId = intent.branch_id;
            }
            return;
        }
        if (intent?.type === "address" && intent.address_id) {
            this.preselectedAddressId = intent.address_id;
        }
        else if (intent?.type === "branch" && intent.branch_id) {
            this.preselectedBranchId = intent.branch_id;
        }
    }
    hasIncompleteUserAddressIntent() {
        if (this.isGuestUser())
            return false;
        const intent = this.getStoredIntent();
        if (!intent || intent.type !== "address" || intent.address_id || !intent.address_details)
            return false;
        // Intent is an address without address_id; consider it "incomplete"
        // only when it represents a valid session-style address.
        return hasSessionAddressIntent(intent);
    }
    hasCompleteIntentForLoggedInUser() {
        if (this.isGuestUser())
            return false;
        const intent = this.getStoredIntent();
        if (!intent)
            return false;
        if (intent.type === "address")
            return !!intent.address_id;
        if (intent.type === "branch")
            return !!intent.branch_id;
        return false;
    }
    /**
     * Authenticated users on the cart page must select/confirm an address before
     * they can dismiss the modal.
     */
    shouldForceNonClosable() {
        if (this.isGuestUser())
            return false;
        if (!Salla.url.is_page("cart"))
            return false;
        return !this.hasCompleteIntentForLoggedInUser();
    }
    shouldPromptIncompleteIntentThisSession() {
        const storage = this.getShownStorage();
        return (this.hasIncompleteUserAddressIntent() &&
            storage.get(this.incompleteIntentPromptKey) !== true);
    }
    markIncompleteIntentPrompted() {
        this.getShownStorage().set(this.incompleteIntentPromptKey, true);
    }
    setStoredIntent(intent) {
        this.getIntentStorage().set(this.intentStorageKey, intent);
        this.overrideScopeSwitchUI();
    }
    clearBulletDeliveryStoredData() {
        // Clear all bullet-delivery keys from both scopes to avoid stale state across auth transitions.
        Salla.storage.session.remove(this.intentStorageKey);
        Salla.storage.store.remove(this.intentStorageKey);
        Salla.storage.session.remove(this.sessionShownKey);
        Salla.storage.session.remove(this.incompleteIntentPromptKey);
        this.overrideScopeSwitchUI();
    }
    /**
     * Single prefill flow: load geography from stored intent and set selected location + form.
     * Assumes this.countries is already loaded. No-op if no intent or no city in intent.
     */
    async prefillAddressFromStoredIntent() {
        const intent = this.getStoredIntent();
        if (!intent || intent.type !== "address" || getIntentCityId(intent) == null)
            return;
        const countryId = getIntentCountryId(intent);
        if (!countryId)
            return;
        const country = this.countries.find((c) => String(c.id) === String(countryId));
        if (!country)
            return;
        this.selectedCountry = country;
        this.updateNewAddressForm({ country_id: Number(country.id) });
        const isSA = isSaudiArabia(country.code);
        const cityId = getIntentCityId(intent);
        const regionId = getIntentRegionId(intent);
        const districtId = getIntentDistrictId(intent);
        const districtName = intent.address_details?.district?.name;
        const [regions, cities, districts] = await Promise.all([
            isSA ? bulletDeliveryAPI.getRegions(country.id) : Promise.resolve([]),
            bulletDeliveryAPI.getCities(country.id, isSA && regionId != null ? regionId : undefined),
            cityId != null
                ? bulletDeliveryAPI.getDistricts(Number(cityId))
                : Promise.resolve([]),
        ]);
        if (isSA) {
            this.regions = regions;
            this.displayedRegions = this.regions;
        }
        this.cities = cities;
        this.displayedCities = this.cities;
        this.districts = districts;
        this.displayedDistricts = this.districts;
        this.loadingCities = false;
        this.loadingRegions = false;
        this.loadingDistricts = false;
        if (isSA && regionId != null) {
            const region = this.regions.find((r) => String(r.id) === String(regionId));
            if (region) {
                this.selectedRegion = region;
                this.updateNewAddressForm({ region_id: region.id });
            }
        }
        if (cityId != null && this.cities.length > 0) {
            const city = this.cities.find((c) => String(c.id) === String(cityId));
            if (city) {
                this.selectedCity = city;
                this.updateNewAddressForm({ city_id: city.id, city });
            }
        }
        if (this.districts.length > 0) {
            const district = this.findPrefillDistrict(districtId, districtName);
            if (district) {
                this.updateNewAddressForm({ district_id: district.id, district });
                this.selectedDistrict = district;
            }
        }
        // When district is captured as free text (or couldn't be matched), keep it in the text input state.
        if (!this.selectedDistrict && districtName) {
            this.districtName = districtName;
        }
    }
    updateNewAddressForm(partial) {
        this.newAddressForm = { ...this.newAddressForm, ...partial };
    }
    /** Whether allocation completed successfully this session (modal won't auto-open again). */
    hasBeenShownThisSession() {
        const storage = this.getShownStorage();
        return storage.get(this.sessionShownKey) === true;
    }
    /** Mark allocation as completed this session (called only after allocateScope succeeds). */
    markShownThisSession() {
        const storage = this.getShownStorage();
        storage.set(this.sessionShownKey, true);
    }
    getIPLocationConfig() {
        const configPath = "store.shipping.delivery_location";
        const ipAddress = {
            countryId: Salla.config.get(`${configPath}.country_id`),
            regionId: Salla.config.get(`${configPath}.region_id`),
            cityId: Salla.config.get(`${configPath}.city_id`),
            districtId: Salla.config.get(`${configPath}.district_id`),
        };
        return localStorage.getItem(OVERRIDE_IP_KEY) ?
            JSON.parse(localStorage.getItem(OVERRIDE_IP_KEY)) : ipAddress;
    }
    async loadCountries(skipEagerSubFetch = false) {
        this.loadingCountries = true;
        const forBranch = this.activeTab === "branch";
        try {
            this.countries = await bulletDeliveryAPI.getCountries(forBranch);
            this.displayedCountries = this.countries;
            const { countryId: configCountryId, regionId: configRegionId, cityId: configCityId, districtId: configDistrictId } = this.getIPLocationConfig();
            log("getIPLocationConfig", this.getIPLocationConfig());
            const countryToSelect = configCountryId && this.countries.length > 0
                ? this.countries.find((c) => String(c.id) === String(configCountryId))
                : null;
            if (countryToSelect) {
                this.selectedCountry = countryToSelect;
                this.updateNewAddressForm({
                    country_id: Number(this.selectedCountry.id),
                });
                // Skip eager sub-fetches when stored intent IDs exist — prefillFromSessionStorage
                // will fire regions/cities/districts in parallel using the stored IDs directly.
                if (!skipEagerSubFetch) {
                    const hasIPLocationIds = configRegionId != null ||
                        configCityId != null ||
                        configDistrictId != null;
                    if (hasIPLocationIds) {
                        await this.prefillFromIPLocation(countryToSelect, {
                            regionId: configRegionId,
                            cityId: configCityId,
                            districtId: configDistrictId,
                        });
                    }
                    else if (isSaudiArabia(this.selectedCountry.code)) {
                        await this.loadRegions(this.selectedCountry.id);
                    }
                    else {
                        await this.loadCities(this.selectedCountry.id);
                    }
                }
            }
        }
        finally {
            this.loadingCountries = false;
        }
    }
    async prefillFromIPLocation(country, ids) {
        const isSA = isSaudiArabia(country.code);
        const { regionId, cityId, districtId } = ids;
        const [regions, cities, districts] = await Promise.all([
            isSA ? bulletDeliveryAPI.getRegions(country.id) : Promise.resolve([]),
            bulletDeliveryAPI.getCities(country.id, isSA && regionId != null ? regionId : undefined),
            cityId != null
                ? bulletDeliveryAPI.getDistricts(Number(cityId))
                : Promise.resolve([]),
        ]);
        if (isSA) {
            this.regions = regions;
            this.displayedRegions = this.regions;
        }
        this.cities = cities;
        this.displayedCities = this.cities;
        this.districts = districts;
        this.displayedDistricts = this.districts;
        this.loadingRegions = false;
        this.loadingCities = false;
        this.loadingDistricts = false;
        if (isSA && regionId != null) {
            const region = this.regions.find((r) => String(r.id) === String(regionId));
            if (region) {
                this.selectedRegion = region;
                this.updateNewAddressForm({ region_id: region.id });
            }
        }
        if (cityId != null && this.cities.length > 0) {
            const city = this.cities.find((c) => String(c.id) === String(cityId));
            if (city) {
                this.selectedCity = city;
                this.updateNewAddressForm({ city_id: city.id, city });
            }
        }
        if (districtId != null && this.districts.length > 0) {
            const district = this.findPrefillDistrict(districtId);
            if (district) {
                this.selectedDistrict = district;
                this.updateNewAddressForm({
                    district_id: district.id,
                    district,
                });
            }
        }
    }
    async loadCities(countryId, regionId) {
        this.loadingCities = true;
        this.cities = [];
        this.displayedCities = [];
        this.districts = [];
        this.displayedDistricts = [];
        this.selectedCity = null;
        this.selectedDistrict = null;
        this.districtName = "";
        try {
            this.cities = await bulletDeliveryAPI.getCities(countryId, regionId);
            this.displayedCities = this.cities;
        }
        finally {
            this.loadingCities = false;
        }
    }
    async loadDistricts(cityId) {
        this.loadingDistricts = true;
        this.districts = [];
        this.displayedDistricts = [];
        this.selectedDistrict = null;
        this.districtName = "";
        try {
            this.districts = await bulletDeliveryAPI.getDistricts(cityId);
            this.displayedDistricts = this.districts;
        }
        finally {
            this.loadingDistricts = false;
        }
    }
    findPrefillDistrict(districtId, districtName) {
        if (this.districts.length === 0) {
            return undefined;
        }
        if (districtId != null) {
            const byId = this.districts.find((d) => String(d.id) === String(districtId));
            if (byId) {
                return byId;
            }
        }
        const normalizedName = districtName?.trim().toLowerCase();
        if (!normalizedName) {
            return undefined;
        }
        return this.districts.find((d) => {
            const arName = d.name?.trim().toLowerCase();
            const enName = d.name_en?.trim().toLowerCase();
            return arName === normalizedName || enName === normalizedName;
        });
    }
    async loadBranches() {
        this.loadingBranches = true;
        try {
            this.branches = await bulletDeliveryAPI.getBranches({
                country_id: this.selectedCountry?.id,
            });
            this.filterBranches();
        }
        finally {
            this.loadingBranches = false;
        }
    }
    filterBranches() {
        this.filteredBranches = filterBranches(this.branches, this.branchSearchQuery);
    }
    /**
     * Prefill form fields from session storage
     */
    async prefillFromSessionStorage() {
        try {
            const intent = this.getStoredIntent();
            if (!intent) {
                return;
            }
            // Prefill address tab for guest users (from stored address_details IDs only)
            if (this.activeTab === "address" &&
                intent.type === "address" &&
                !this.isLoggedIn) {
                await this.prefillAddressFromStoredIntent();
            }
            // Prefill branch tab
            if (this.activeTab === "branch" && intent.type === "branch") {
                const countryId = getIntentCountryId(intent);
                if (countryId != null) {
                    const country = this.countries.find((c) => String(c.id) === String(countryId));
                    if (country) {
                        this.selectedCountry = country;
                        this.updateNewAddressForm({ country_id: Number(country.id) });
                        const branchId = getIntentBranchId(intent);
                        if (branchId != null && this.branches.length > 0) {
                            const branch = this.branches.find((b) => b.id === branchId);
                            if (branch) {
                                this.selectedBranch = branch;
                            }
                        }
                    }
                }
            }
        }
        catch (error) {
            console.error("[BulletDelivery] Error prefilling from session storage:", error);
        }
    }
    async loadSavedAddresses() {
        this.savedAddresses = await bulletDeliveryAPI.getSavedAddresses();
        const intent = this.getStoredIntent();
        const hasSessionAddress = hasSessionAddressIntent(intent);
        if (hasSessionAddress) {
            this.selectedSessionAddress = true;
            this.selectedSavedAddress = null;
        }
        else {
            const defaultAddress = this.savedAddresses.find((a) => a.is_default && a.is_in_coverage !== false);
            if (defaultAddress) {
                this.selectedSavedAddress = defaultAddress;
            }
            else {
                const validAddress = this.savedAddresses.find((a) => a.is_in_coverage !== false);
                if (validAddress) {
                    this.selectedSavedAddress = validAddress;
                }
            }
        }
    }
    applyCountryChange(newCountry) {
        this.selectedCountry = newCountry;
        this.selectedRegion = null;
        this.regions = [];
        this.displayedRegions = [];
        this.cities = [];
        this.displayedCities = [];
        this.districts = [];
        this.displayedDistricts = [];
        this.selectedCity = null;
        this.selectedDistrict = null;
        this.districtName = "";
        this.allocationOutOfCoverageMessage = null;
        this.regionSearchQuery = '';
        this.citySearchQuery = '';
        this.districtSearchQuery = '';
        this.searchingRegions = false;
        this.searchingCities = false;
        this.searchingDistricts = false;
        this.clearSearchTimers();
        if (this.selectedCountry) {
            this.updateNewAddressForm({
                country_id: Number(this.selectedCountry.id),
                region_id: undefined,
                city_id: undefined,
                district_id: undefined,
                city: undefined,
                district: undefined,
            });
            if (this.activeTab === "branch") {
                this.loadBranches();
            }
            else if (isSaudiArabia(this.selectedCountry.code)) {
                this.loadRegions(this.selectedCountry.id);
            }
            else {
                this.loadCities(this.selectedCountry.id);
            }
        }
    }
    async loadRegions(countryId) {
        this.loadingRegions = true;
        this.regions = [];
        this.displayedRegions = [];
        this.selectedRegion = null;
        this.cities = [];
        this.displayedCities = [];
        this.districts = [];
        this.displayedDistricts = [];
        this.selectedCity = null;
        this.selectedDistrict = null;
        this.districtName = "";
        try {
            this.regions = await bulletDeliveryAPI.getRegions(countryId);
            this.displayedRegions = this.regions;
        }
        finally {
            this.loadingRegions = false;
        }
    }
    emitHeaderContextUpdate(result, address, branch) {
        let locationText = "";
        if (result.type === "address") {
            if (address) {
                locationText =
                    address.district?.name && address.city?.name
                        ? `${address.district.name}، ${address.city.name}`
                        : (address.city?.name ?? "");
            }
            else if (this.selectedCity) {
                locationText = this.selectedDistrict
                    ? `${this.selectedDistrict.name}، ${this.selectedCity.name}`
                    : this.selectedCity.name;
            }
            else if (result.address_details) {
                const parts = [
                    result.address_details.district?.name,
                    result.address_details.city.name,
                    result.address_details.country.name,
                ].filter(Boolean);
                locationText =
                    parts.join("، ") || result.address_details.short_address || "";
            }
        }
        else if (branch) {
            locationText = branch.name;
        }
        else if (result.branch_details) {
            locationText = result.branch_details.city ?? result.branch_details.name;
        }
        // Build display text with prefix (e.g., "Delivering to: Riyadh" or "Pickup from: Branch Name")
        const prefix = result.type === "address"
            ? Salla.lang.get("mobile_app.strings.delivery")
            : Salla.lang.get("mobile_app.strings.pickup");
        const displayText = locationText ? `${prefix}: ${locationText}` : "";
        this.headerContextUpdate.emit({
            type: result.type,
            display_text: displayText,
            country_code: result.country_code,
            city: this.selectedCity?.name ?? result.address_details?.city?.name,
            district: this.selectedDistrict?.name ?? result.address_details?.district?.name,
            branch_name: branch?.name ?? result.branch_details?.name,
        });
    }
    handleBranchSearch(event) {
        const input = event.target;
        const query = input.value;
        this.branchSearchQuery = query;
        if (this.branchSearchDebounceTimer)
            clearTimeout(this.branchSearchDebounceTimer);
        if (!query?.trim()) {
            this.branchSearchQuery = "";
            void this.loadBranches();
            return;
        }
        this.branchSearchDebounceTimer = setTimeout(async () => {
            if (query.trim().length < 2)
                return;
            this.loadingBranches = true;
            try {
                this.branches = await bulletDeliveryAPI.getBranches({
                    country_id: this.selectedCountry?.id,
                    query,
                });
                this.filterBranches();
            }
            finally {
                this.loadingBranches = false;
            }
        }, BRANCH_SEARCH_DEBOUNCE_MS);
    }
    clearSearchTimers() {
        [this.countrySearchTimer, this.regionSearchTimer, this.citySearchTimer, this.districtSearchTimer]
            .forEach(t => {
            if (t)
                clearTimeout(t);
        });
        this.countrySearchTimer = this.regionSearchTimer = this.citySearchTimer = this.districtSearchTimer = null;
    }
    resetSearchState() {
        this.countrySearchQuery = '';
        this.regionSearchQuery = '';
        this.citySearchQuery = '';
        this.districtSearchQuery = '';
        this.searchingCountries = false;
        this.searchingRegions = false;
        this.searchingCities = false;
        this.searchingDistricts = false;
        this.displayedCountries = [];
        this.displayedRegions = [];
        this.displayedCities = [];
        this.displayedDistricts = [];
        this.clearSearchTimers();
    }
    async loadBranchesWithLocation(lat, lng) {
        this.loadingBranches = true;
        try {
            this.branches = await bulletDeliveryAPI.getBranches({
                country_id: this.selectedCountry?.id,
                lat,
                lng,
            });
            this.filterBranches();
            // Auto-select country from first branch if no country is selected
            if (!this.selectedCountry && this.branches.length > 0) {
                const firstBranch = this.branches[0];
                if (firstBranch.country) {
                    const matchingCountry = this.countries.find((c) => c.id === firstBranch.country.id);
                    if (matchingCountry) {
                        this.selectedCountry = matchingCountry;
                        this.updateNewAddressForm({
                            country_id: Number(matchingCountry.id),
                        });
                    }
                }
            }
        }
        finally {
            this.loadingBranches = false;
        }
    }
    /** Locate nearest branch using device geolocation (branches tab only). */
    async handleFindNearestBranch() {
        if (!navigator.geolocation) {
            this.locationError = Salla.lang.get("pages.checkout.current_location_not_supported");
            return;
        }
        this.loadingNearestBranch = true;
        this.locationError = "";
        try {
            const position = await new Promise((resolve, reject) => {
                navigator.geolocation.getCurrentPosition(resolve, reject, {
                    enableHighAccuracy: true,
                    timeout: GEOLOCATION_TIMEOUT,
                    maximumAge: 0,
                });
            });
            const { latitude, longitude } = position.coords;
            await this.loadBranchesWithLocation(latitude, longitude);
            const nearestBranch = findNearestBranch(this.branches, latitude, longitude);
            if (nearestBranch) {
                this.selectedBranch = nearestBranch;
                this.branchSearchQuery = "";
                this.filterBranches();
            }
        }
        catch (error) {
            const geoError = error;
            const code = typeof geoError?.code === "number" ? geoError.code : -1;
            this.locationError = getGeolocationErrorMessage(code);
        }
        finally {
            this.loadingNearestBranch = false;
        }
    }
    handleBranchSelect(branch) {
        this.selectedBranch = branch;
    }
    handleSavedAddressSelect(address) {
        if (address.is_in_coverage === false) {
            // Show toast notification for out of coverage address
            Salla.notify?.error(Salla.lang.get("pages.checkout.shipping_not_available"));
            return;
        }
        this.selectedSavedAddress = address;
        this.selectedSessionAddress = false;
    }
    handleSessionAddressSelect() {
        this.selectedSessionAddress = true;
        this.selectedSavedAddress = null;
    }
    /** Show delete confirmation UI for this address (do not call API yet). */
    /**
     * Switch to add-address form (unified form). Preselects country from session when present.
     */
    async handleAddNewAddress() {
        this.viewMode = "add-address";
        const intent = this.getStoredIntent();
        const sessionCountryId = getIntentCountryId(intent);
        if (sessionCountryId && this.countries.length > 0) {
            const country = this.countries.find((c) => c.id === sessionCountryId);
            if (country) {
                this.selectedCountry = country;
                this.updateNewAddressForm({ country_id: Number(country.id) });
                if (isSaudiArabia(country.code)) {
                    await this.loadRegions(country.id);
                }
                else {
                    await this.loadCities(country.id);
                }
            }
        }
    }
    handleBackToAddressList() {
        this.viewMode = "main";
    }
    /**
     * Build address/location payload from guest-form state (same fields as add-address).
     */
    buildAddressLocationPayload() {
        const districtName = this.selectedDistrict?.name ?? this.districtName?.trim() ?? "";
        return buildAddressLocationPayloadFromSelection({
            countryId: this.selectedCountry?.id ?? 0,
            countryCode: this.selectedCountry?.code,
            regionId: this.selectedRegion?.id,
            cityId: this.selectedCity?.id,
            districtId: this.selectedDistrict?.id,
            description: districtName,
        });
    }
    async handleTabChange(tab) {
        if (this.tabChanging)
            return;
        this.tabChanging = true;
        try {
            this.activeTab = tab;
            this.showCartWillBeClearedBanner = false;
            this.allocationOutOfCoverageMessage = null;
            this.resetSearchState();
            const forBranch = tab === "branch";
            this.countries = await bulletDeliveryAPI.getCountries(forBranch);
            this.displayedCountries = this.countries;
            const previousCountryId = this.selectedCountry?.id;
            if (previousCountryId !== undefined && previousCountryId !== null) {
                this.selectedCountry =
                    this.countries.find((c) => c.id === previousCountryId) || null;
            }
            // Fallback to IP-detected country when carry-over fails
            if (!this.selectedCountry) {
                const { countryId: configCountryId } = this.getIPLocationConfig();
                if (configCountryId && this.countries.length > 0) {
                    this.selectedCountry =
                        this.countries.find((c) => String(c.id) === String(configCountryId)) || null;
                }
                if (!this.selectedCountry && this.countries.length === 1) {
                    this.selectedCountry = this.countries[0];
                }
            }
            // Load appropriate data when switching tabs if country is selected
            if (this.selectedCountry) {
                if (tab === "branch") {
                    // Load branches when switching to branch tab
                    // Check session storage for lat/lng to get nearby branches
                    const savedIntent = this.getStoredIntent();
                    const intentLat = getIntentLatitude(savedIntent);
                    const intentLng = getIntentLongitude(savedIntent);
                    if (intentLat != null && intentLng != null) {
                        await this.loadBranchesWithLocation(intentLat, intentLng);
                    }
                    else {
                        await this.loadBranches();
                    }
                    // Preselect branch from session storage if available
                    const branchId = getIntentBranchId(savedIntent);
                    if (branchId != null && this.branches.length > 0) {
                        const branch = this.branches.find((b) => b.id === branchId);
                        if (branch) {
                            this.selectedBranch = branch;
                        }
                    }
                }
                else if (tab === "address") {
                    // Lazy-load saved addresses when switching to address tab (if not loaded yet).
                    if (this.isLoggedIn && !this.savedAddressesLoaded) {
                        this.loadingSavedAddresses = true;
                        try {
                            await this.loadSavedAddresses();
                            this.savedAddressesLoaded = true;
                        }
                        finally {
                            this.loadingSavedAddresses = false;
                        }
                    }
                    if (!this.isLoggedIn) {
                        const savedIntent = this.getStoredIntent();
                        if (savedIntent && getIntentCityId(savedIntent)) {
                            await this.prefillAddressFromStoredIntent();
                        }
                    }
                }
            }
        }
        finally {
            this.tabChanging = false;
        }
    }
    isConfirmDisabled() {
        if (this.activeTab === "branch") {
            return !this.selectedBranch;
        }
        if (this.activeTab === "address") {
            if (this.isLoggedIn && this.selectedSessionAddress) {
                return false; // Session address selected - confirm will save then allocate
            }
            if (this.isLoggedIn && this.selectedSavedAddress) {
                return this.selectedSavedAddress.is_in_coverage === false;
            }
            // Guest: require country + city; for SA require region + district
            if (!this.selectedCountry || !this.selectedCity)
                return true;
            return !requireRegionAndDistrictForSA(this.selectedCountry?.code, this.selectedRegion?.id, this.selectedDistrict?.id ?? (this.districtName?.trim() || null));
        }
        return false;
    }
    handleLogin() {
        // Keep bullet-delivery flow in-place and avoid full page reload after login.
        Salla.auth.setCanRedirect(false);
        Salla.event.dispatch("salla::bullet-delivery.modal.close.requested");
        Salla.event.dispatch("login::open", Salla.url.is_page("cart")
            ? { withoutReload: true, source: "cart-submit" }
            : { withoutReload: true, source: "bullet-delivery" });
    }
    resolvePendingCartSubmit() {
        if (!this.pendingCartSubmitResolver)
            return;
        const resolve = this.pendingCartSubmitResolver;
        this.pendingCartSubmitResolver = null;
        this.pendingCartSubmitPromise = null;
        this.cartSubmitConfirmationPending = false;
        resolve();
    }
    buildIntentAddress() {
        if (this.activeTab !== "address" ||
            !this.selectedCountry ||
            !this.selectedCity) {
            return undefined;
        }
        const country = {
            id: this.selectedCountry.id,
            name: this.selectedCountry.name,
            code: this.selectedCountry.code,
        };
        const city = {
            id: this.selectedCity.id,
            name: this.selectedCity.name,
        };
        const region = this.selectedRegion
            ? {
                id: this.selectedRegion.id,
                name: this.selectedRegion.name,
                code: this.selectedRegion.code,
            }
            : undefined;
        const district = this.selectedDistrict
            ? { id: this.selectedDistrict.id, name: this.selectedDistrict.name }
            : this.districtName
                ? { id: 0, name: this.districtName }
                : undefined;
        const short_address = this.selectedSavedAddress?.short_address;
        return {
            country,
            region,
            city,
            district,
            short_address,
        };
    }
    buildIntentAddressFromSaved(addr) {
        return {
            country: {
                id: addr.country?.id ?? addr.country_id ?? 0,
                name: addr.country?.name ?? "",
                code: addr.country?.code,
            },
            region: addr.region
                ? { id: addr.region.id, name: addr.region.name, code: addr.region.code }
                : undefined,
            city: {
                id: addr.city?.id ?? addr.city_id ?? 0,
                name: addr.city?.name ?? "",
            },
            district: addr.district
                ? { id: addr.district.id, name: addr.district.name }
                : undefined,
            short_address: addr.short_address,
        };
    }
    buildIntentBranch() {
        if (this.activeTab !== "branch" || !this.selectedBranch)
            return undefined;
        const b = this.selectedBranch;
        const lat = b.location?.lat != null ? Number(b.location.lat) : undefined;
        const lng = b.location?.lng != null ? Number(b.location.lng) : undefined;
        return {
            id: b.id,
            name: b.name,
            city: b.city?.name,
            latitude: lat,
            longitude: lng,
        };
    }
    buildAllocationConfirmedAddressData(selectedAddress) {
        if (this.activeTab !== "address")
            return null;
        return {
            saved_address: selectedAddress ?? this.selectedSavedAddress ?? undefined,
            country: this.selectedCountry ?? undefined,
            region: this.selectedRegion ?? undefined,
            city: this.selectedCity ?? undefined,
            district: this.selectedDistrict ?? undefined,
            district_name: this.districtName?.trim() || undefined,
            short_address: selectedAddress?.short_address ?? this.selectedSavedAddress?.short_address,
            form_data: { ...this.newAddressForm },
        };
    }
    /**
     * Build a minimal `BulletDeliveryAllocationConfirmedAddressData` from a mobile
     * payload (no full SavedAddress object available). Only used for the
     * `salla::bullet-delivery.allocation.confirmed` event so existing listeners
     * keep working with the same shape they get on desktop.
     */
    buildAllocationConfirmedAddressFromIntent(payload) {
        if (payload.type !== "address")
            return null;
        const details = payload.address_details;
        const countryId = Number(payload.country_id) || 0;
        return {
            country: details?.country
                ? {
                    id: details.country.id,
                    name: details.country.name,
                    code: details.country.code ?? payload.country_code ?? "",
                }
                : undefined,
            region: details?.region
                ? {
                    id: Number(details.region.id),
                    name: details.region.name,
                    country_id: countryId,
                    code: details.region.code ?? undefined,
                }
                : undefined,
            city: details?.city
                ? {
                    id: Number(details.city.id),
                    name: details.city.name,
                    country_id: countryId,
                }
                : undefined,
            district: details?.district
                ? {
                    id: Number(details.district.id),
                    name: details.district.name,
                    city_id: Number(details.city?.id) || 0,
                }
                : undefined,
            short_address: details?.short_address,
        };
    }
    /** Synthesise a minimal `Branch` from a mobile branch intent. */
    buildBranchFromIntent(payload) {
        if (payload.type !== "branch" || !payload.branch_details)
            return null;
        const b = payload.branch_details;
        const branch = {
            id: b.id,
            name: b.name,
        };
        if (b.city) {
            branch.city = { id: 0, name: b.city };
        }
        if (b.latitude != null && b.longitude != null) {
            branch.location = { lat: String(b.latitude), lng: String(b.longitude) };
        }
        return branch;
    }
    /** Reconstruct the equivalent `ScopeAllocationPayload` from a mobile result. */
    buildAllocationRequestFromIntent(payload) {
        if (payload.type === "branch") {
            return {
                type: "branch",
                branch_id: payload.branch_id != null ? String(payload.branch_id) : "",
            };
        }
        if (payload.address_id != null) {
            return {
                type: "address",
                address_id: String(payload.address_id),
            };
        }
        const details = payload.address_details;
        const request = {
            type: "address",
            country_id: payload.country_id != null ? String(payload.country_id) : "",
            city_id: details?.city?.id != null ? String(details.city.id) : "",
        };
        if (details?.region?.id != null) {
            request.region_id = String(details.region.id);
        }
        if (details?.district?.id != null) {
            request.district_id = String(details.district.id);
        }
        return request;
    }
    /**
     * Apply a selection performed inside the mobile app's native sheet.
     *
     * Mirrors the post-allocation side-effects of `handleConfirm()` so the
     * webview ends up in the exact same state as if the user had confirmed via
     * our component on desktop:
     *   1. Sets `s-scope-allocation-*` headers for subsequent API calls.
     *   2. Persists allocation in `Salla.storage.scope` (single source of truth).
     *   3. Marks the modal as shown for this session and stores the intent so
     *      delivery-promise / scope-switch UIs reflect the selection.
     *   4. Clears the API cache so cached data from the previous scope is gone.
     *   5. Dispatches `salla::bullet-delivery.allocation.confirmed`,
     *      `bulletDeliveryConfirmed`, and the header-context update event so
     *      every listener (header pill, cart view, etc.) syncs.
     *   6. Reloads the page so prices, availability, and cart reflect the
     *      newly-selected scope (matches desktop behaviour).
     */
    applyMobileBulletDeliverySelection(payload) {
        if (!payload || (payload.type !== "address" && payload.type !== "branch")) {
            console.warn("SallaBulletDelivery: ignoring invalid mobile select payload", payload);
            return;
        }
        const headers = payload.allocation_headers ?? {};
        const allocationType = headers["s-scope-allocation-type"] ?? payload.type;
        const allocationId = headers["s-scope-allocation-id"];
        if (allocationType) {
            Salla.api.setHeader("s-scope-allocation-type", allocationType);
        }
        if (allocationId) {
            Salla.api.setHeader("s-scope-allocation-id", String(allocationId));
        }
        const existingScope = Salla.config.get("store.scope", Salla.storage.get("scope")) || {};
        Salla.storage.set("scope", {
            ...existingScope,
            allocation_type: allocationType,
            allocation_id: allocationId ? String(allocationId) : undefined,
        });
        this.markShownThisSession();
        // Normalise headers in the persisted intent: keep only the mobile-provided
        // values so storefront reads see the same shape as the desktop confirm flow.
        const normalisedIntent = {
            ...payload,
            allocation_headers: {
                "s-scope-allocation-type": allocationType,
                "s-scope-allocation-id": allocationId
                    ? String(allocationId)
                    : undefined,
            },
        };
        this.setStoredIntent(normalisedIntent);
        clearApiCache();
        const branch = this.buildBranchFromIntent(normalisedIntent);
        const allocationConfirmedPayload = {
            ...normalisedIntent,
            address: this.buildAllocationConfirmedAddressFromIntent(normalisedIntent),
            branch,
            allocation_request: this.buildAllocationRequestFromIntent(normalisedIntent),
            allocation_response: null,
        };
        Salla.event.dispatch("salla::bullet-delivery.allocation.confirmed", allocationConfirmedPayload);
        this.bulletDeliveryConfirmed.emit({
            ...normalisedIntent,
            branch: branch ?? undefined,
        });
        this.emitHeaderContextUpdate(normalisedIntent, undefined, branch ?? undefined);
        // Reload so products / cart / header reflect the new scope, matching the
        // desktop confirm flow. Small delay lets the dispatched events propagate
        // to any in-page listeners before the navigation tears the document down.
        setTimeout(() => window.location.reload(), 100);
    }
    extractMobileSelectPayload(raw) {
        if (!raw || typeof raw !== "object")
            return null;
        // Some mobile bridges deliver the original `{ event, payload }` envelope
        // while a normal Salla.event dispatch passes the data directly.
        if ("payload" in raw && raw.payload) {
            return raw.payload;
        }
        return raw;
    }
    async handleConfirm() {
        if (this.isConfirmDisabled() || this.confirming)
            return;
        this.confirming = true;
        this.confirmBtn?.load();
        let scheduledRedirect = false;
        try {
            const result = {
                type: this.activeTab,
                country_id: Number(this.selectedCountry?.id) || 0,
                country_code: this.selectedCountry?.code || "",
            };
            let selectedAddress;
            let selectedBranchData;
            if (this.activeTab === "address") {
                if (this.isLoggedIn && this.selectedSessionAddress) {
                    const savedAddress = await this.saveSessionAddressToProfile();
                    if (!savedAddress) {
                        Salla.notify?.error(Salla.lang.get("common.errors.error_occurred"));
                        this.confirmBtn?.stop();
                        return;
                    }
                    result.address_id = savedAddress.id;
                    selectedAddress = savedAddress;
                    this.selectedSessionAddress = false;
                    this.selectedSavedAddress = savedAddress;
                    result.address_details = this.buildIntentAddressFromSaved(savedAddress);
                }
                else if (this.isLoggedIn && this.selectedSavedAddress) {
                    result.address_id = this.selectedSavedAddress.id;
                    selectedAddress = this.selectedSavedAddress;
                    result.address_details = this.buildIntentAddressFromSaved(this.selectedSavedAddress);
                }
                else {
                    result.address_details = this.buildIntentAddress();
                }
            }
            else {
                result.branch_details = this.buildIntentBranch();
                result.branch_id = this.selectedBranch?.id;
                selectedBranchData = this.selectedBranch || undefined;
            }
            // Build scope allocation payload based on scenario
            let allocationPayload;
            if (this.activeTab === "address") {
                if (this.isLoggedIn && this.selectedSavedAddress) {
                    // Case 2: Logged-in user with saved address
                    allocationPayload = {
                        type: "address",
                        address_id: String(this.selectedSavedAddress.id),
                    };
                }
                else {
                    // Case 1: Guest user or logged-in user without saved address
                    allocationPayload = {
                        type: "address",
                        country_id: String(this.selectedCountry?.id || 0),
                        city_id: String(this.selectedCity?.id || ""),
                    };
                    if (isSaudiArabia(this.selectedCountry?.code ?? '')) {
                        if (this.selectedRegion?.id) {
                            allocationPayload.region_id = String(this.selectedRegion.id);
                        }
                        allocationPayload.district_id = String(this.selectedDistrict?.id || "");
                    }
                }
            }
            else {
                // Case 3: Pickup
                allocationPayload = {
                    type: "branch",
                    branch_id: String(this.selectedBranch?.id || ""),
                };
            }
            // Make API call to allocate scope
            const allocationResult = await bulletDeliveryAPI.allocateScope(allocationPayload);
            if (!allocationResult.success) {
                console.error("BulletDelivery: Scope allocation failed", allocationResult.error);
                const errorMessage = allocationResult.error ||
                    (this.activeTab === "address"
                        ? Salla.lang.get("pages.checkout.address_out_of_coverage")
                        : Salla.lang.get("pages.checkout.failed_to_set_pickup"));
                this.allocationOutOfCoverageMessage = errorMessage;
                this.confirmBtn?.stop();
                this.confirming = false;
                return;
            }
            // Process successful allocation response
            let allocatedScopeId;
            if (allocationResult.data) {
                const allocationData = allocationResult.data;
                allocatedScopeId = allocationData.id;
                const allocationType = allocationData?.allocation?.type;
                const allocationBranchId = allocationData?.allocation?.branch_id;
                // Set headers via Salla.api.setHeader
                if (allocationType) {
                    Salla.api.setHeader("s-scope-allocation-type", allocationType);
                }
                if (allocationBranchId) {
                    Salla.api.setHeader("s-scope-allocation-id", String(allocationBranchId));
                }
                // Persist allocation data in scope storage (single source of truth for all components)
                const existingScope = Salla.config.get("store.scope", Salla.storage.get("scope")) || {};
                Salla.storage.set("scope", {
                    ...existingScope,
                    id: allocatedScopeId,
                    allocation_type: allocationType,
                    allocation_id: allocationBranchId
                        ? String(allocationBranchId)
                        : undefined,
                });
                // Store headers in result object for persistence after page reload
                result.allocation_headers = {
                    "s-scope-allocation-type": allocationType,
                    "s-scope-allocation-id": allocationBranchId
                        ? String(allocationBranchId)
                        : undefined,
                };
            }
            // After allocation success: mark session so we don't show modal again this session
            this.markShownThisSession();
            // After allocation success: persist latest intent so switch UI can always reflect
            // the selected address/branch once confirmed.
            this.setStoredIntent(result);
            if (allocatedScopeId) {
                await bulletDeliveryAPI.setDeliveryScope(allocatedScopeId);
                clearApiCache();
            }
            const allocationConfirmedPayload = {
                ...result,
                address: this.buildAllocationConfirmedAddressData(selectedAddress),
                branch: selectedBranchData ?? null,
                allocation_request: allocationPayload,
                allocation_response: allocationResult.data ?? null,
            };
            Salla.event.dispatch("salla::bullet-delivery.allocation.confirmed", allocationConfirmedPayload);
            this.bulletDeliveryConfirmed.emit({
                ...result,
                address: selectedAddress,
                branch: selectedBranchData,
            });
            // Emit header context update for global header sync
            this.emitHeaderContextUpdate(result, selectedAddress, selectedBranchData);
            scheduledRedirect = true;
            setTimeout(() => {
                this.confirmBtn?.stop();
                this.close();
                this.confirming = false;
                if (this.cartSubmitConfirmationPending) {
                    this.resolvePendingCartSubmit();
                    return;
                }
                if (allocatedScopeId) {
                    const scope = Salla.storage.get("scope") || {};
                    let url = Salla.helpers.addParamToUrl("scope", allocatedScopeId);
                    if (scope.allocation_id) {
                        url = Salla.helpers.addParamToUrl("allocation_id", scope.allocation_id, url);
                    }
                    if (scope.allocation_type) {
                        url = Salla.helpers.addParamToUrl("allocation_type", scope.allocation_type, url);
                    }
                    window.location.replace(url);
                }
                else {
                    window.location.reload();
                }
            }, 500);
        }
        finally {
            if (!scheduledRedirect) {
                this.confirming = false;
            }
        }
    }
    getCartViewConfig(intent) {
        if (!intent || !Salla.url.is_page("cart"))
            return null;
        const isBranch = intent.type === "branch";
        const isAddress = intent.type === "address";
        if ((isBranch && !this.supportsPickup) || (!isBranch && !isAddress))
            return null;
        return {
            title: isBranch
                ? Salla.lang.get("pages.checkout.pickup_option")
                : Salla.lang.get("pages.checkout.delivery_option"),
            subtitle: getIntentSubtitle(intent, Salla.lang.get("common.elements.to"), ""),
            buttonText: Salla.lang.get("common.elements.edit"),
            isAddress,
            intent,
        };
    }
    /** Creates the cart view DOM for mounting into cart.items.start hook */
    createCartViewElement() {
        const intent = this.getStoredIntent();
        const config = this.getCartViewConfig(intent);
        if (!config)
            return null;
        const { title, subtitle, buttonText, intent: configIntent } = config;
        const openPayload = configIntent.type === "branch"
            ? { preselected_branch_id: getIntentBranchId(configIntent) }
            : { preselected_address_id: configIntent.address_id };
        const icon = document.createElement("span");
        icon.className =
            "s-bullet-delivery-cart-view-icon s-bullet-delivery-tab-icon";
        icon.setAttribute("aria-hidden", "true");
        icon.innerHTML = Location;
        const titleEl = document.createElement("span");
        titleEl.className = "s-bullet-delivery-cart-view-title";
        titleEl.textContent = title;
        const subtitleEl = document.createElement("span");
        subtitleEl.className = "s-bullet-delivery-cart-view-subtitle";
        subtitleEl.textContent = subtitle;
        const text = document.createElement("div");
        text.className = "s-bullet-delivery-cart-view-text";
        text.append(titleEl, subtitleEl);
        const info = document.createElement("div");
        info.className = "s-bullet-delivery-cart-view-info";
        info.append(icon, text);
        const btn = document.createElement("salla-button");
        btn.className = "s-bullet-delivery-cart-view-button";
        btn.setAttribute("fill", "outline");
        btn.setAttribute("color", "primary");
        btn.textContent = buttonText;
        btn.addEventListener("click", () => Salla.event.emit("salla::bullet-delivery.modal.open.requested", openPayload));
        const wrapper = document.createElement("div");
        wrapper.className = "s-bullet-delivery-cart-view";
        wrapper.append(info, btn);
        return wrapper;
    }
    renderTabs() {
        // Show tabs only when pickup is supported; otherwise delivery-only view with no tabs
        if (!this.supportsPickup)
            return null;
        return (h("div", { class: "s-bullet-delivery-tabs" }, h("button", { type: "button", class: {
                "s-bullet-delivery-tab": true,
                "s-bullet-delivery-tab--active": this.activeTab === "address",
            }, onClick: () => this.handleTabChange("address") }, h("span", { class: "s-bullet-delivery-tab-icon", innerHTML: Location, "aria-hidden": "true" }), h("span", null, Salla.lang.get("mobile_app.strings.delivery"))), h("button", { type: "button", class: {
                "s-bullet-delivery-tab": true,
                "s-bullet-delivery-tab--active": this.activeTab === "branch",
            }, onClick: () => this.handleTabChange("branch") }, h("span", { class: "s-bullet-delivery-tab-icon", innerHTML: Store, "aria-hidden": "true" }), h("span", null, Salla.lang.get("mobile_app.strings.pickup")))));
    }
    renderAlert(message) {
        return (h("div", { class: "s-bullet-delivery-allocation-out-of-coverage", role: "alert" }, h("span", { class: "s-bullet-delivery-allocation-out-of-coverage-icon", "aria-hidden": "true" }, h("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", role: "img", "aria-hidden": "true" }, h("title", null, "Information"), h("circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", "stroke-width": "1.5", fill: "currentColor" }), h("text", { x: "10", y: "14", "text-anchor": "middle", fill: "white", "font-size": "12", "font-weight": "bold" }, "i"))), h("span", { class: "s-bullet-delivery-allocation-out-of-coverage-text" }, message)));
    }
    renderAllocationOutOfCoverageAlert() {
        const message = this.allocationOutOfCoverageMessage ||
            Salla.lang.get("pages.checkout.shipping_not_available");
        return this.renderAlert(message);
    }
    renderCountrySelect() {
        return (h("div", { class: "s-bullet-delivery-field" }, h("salla-searchable-dropdown", { label: Salla.lang.get("blocks.buy_as_gift.receiver_country"), placeholder: Salla.lang.get("pages.checkout.select_country"), items: this.displayedCountries, selectedItem: this.selectedCountry, loading: this.loadingCountries, searching: this.searchingCountries, disabled: this.countries.length <= 1, required: true, inputId: "bullet-delivery-country", searchQuery: this.countrySearchQuery, clientSearch: true, onItemSelected: (e) => this.handleCountrySelected(e.detail), onSearchInput: (e) => this.handleCountrySearch(e.detail), onDropdownClosed: () => this.handleCountryDropdownClosed() })));
    }
    /** Region select (SA only): shown when SA is selected; city and district disabled until region selected. */
    renderRegionSelect() {
        const isSA = isSaudiArabia(this.selectedCountry?.code ?? '');
        if (!isSA || !this.selectedCountry)
            return null;
        return (h("div", { class: "s-bullet-delivery-field" }, h("salla-searchable-dropdown", { label: Salla.lang.get("pages.checkout.region_field"), placeholder: Salla.lang.get("pages.checkout.select_region"), items: this.displayedRegions, selectedItem: this.selectedRegion, loading: this.loadingRegions, searching: this.searchingRegions, disabled: this.loadingRegions || this.regions.length === 0, required: true, inputId: "bullet-delivery-region", searchQuery: this.regionSearchQuery, clientSearch: true, onItemSelected: (e) => this.handleRegionSelected(e.detail), onSearchInput: (e) => this.handleRegionSearch(e.detail), onDropdownClosed: () => this.handleRegionDropdownClosed() })));
    }
    renderCityDistrictSelects() {
        const isSA = isSaudiArabia(this.selectedCountry?.code ?? '');
        const showDistrict = isSA;
        const showDistrictInput = showDistrict &&
            this.selectedCity &&
            !this.loadingDistricts &&
            this.districts.length === 0;
        const cityDisabled = !this.selectedCountry ||
            (isSA && !this.selectedRegion) ||
            this.loadingCities ||
            this.cities.length === 0;
        const districtDisabled = !this.selectedCountry ||
            (isSA && !this.selectedRegion) ||
            !this.selectedCity ||
            this.loadingDistricts;
        return (h("div", { class: "s-bullet-delivery-field-row" }, h("div", { class: "s-bullet-delivery-field" }, h("salla-searchable-dropdown", { label: Salla.lang.get("blocks.buy_as_gift.receiver_city"), placeholder: Salla.lang.get("pages.checkout.select_city"), items: this.displayedCities, selectedItem: this.selectedCity, loading: this.loadingCities, searching: this.searchingCities, disabled: cityDisabled, required: true, inputId: "bullet-delivery-city", searchQuery: this.citySearchQuery, onItemSelected: (e) => this.handleCitySelected(e.detail), onSearchInput: (e) => this.handleCitySearch(e.detail), onDropdownClosed: () => this.handleCityDropdownClosed(), dropUp: true })), showDistrict && (h("div", { class: "s-bullet-delivery-field" }, showDistrictInput ? (h("div", null, h("label", { class: "s-bullet-delivery-label", htmlFor: "bullet-delivery-district" }, Salla.lang.get("pages.checkout.district_field"), h("span", { class: "text-red-500" }, " *")), h("input", { id: "bullet-delivery-district", type: "text", class: "form-input", placeholder: Salla.lang.get("pages.checkout.select_district"), value: this.districtName, disabled: districtDisabled, onInput: (e) => {
                const input = e.target;
                this.districtName = input.value;
                this.updateNewAddressForm({ district: undefined });
            } }))) : (h("salla-searchable-dropdown", { label: Salla.lang.get("pages.checkout.district_field"), placeholder: Salla.lang.get("pages.checkout.select_district"), items: this.displayedDistricts, selectedItem: this.selectedDistrict, loading: this.loadingDistricts, searching: this.searchingDistricts, disabled: districtDisabled || this.districts.length === 0, required: true, inputId: "bullet-delivery-district", searchQuery: this.districtSearchQuery, clientSearch: true, onItemSelected: (e) => this.handleDistrictSelected(e.detail), onSearchInput: (e) => this.handleDistrictSearch(e.detail), onDropdownClosed: () => this.handleDistrictDropdownClosed(), dropUp: true }))))));
    }
    renderSavedAddressesEmptyState() {
        return (h("div", { class: "s-bullet-delivery-saved-addresses-empty" }, h("div", { class: "s-bullet-delivery-saved-addresses-empty-icon", "aria-hidden": "true" }, h("svg", { width: "28", height: "28", viewBox: "0 0 28 29", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("title", null, "No Saved Adresses"), h("path", { d: "M20.16 0C21.4613 0 22.6773 0.341333 23.808 1.024C24.9387 1.70667 25.8347 2.61333 26.496 3.744C27.1787 4.91733 27.52 6.18667 27.52 7.552C27.52 9.45067 26.8267 11.232 25.44 12.896C24.4587 14.0907 23.0827 15.2427 21.312 16.352H21.28C20.9387 16.5653 20.5653 16.672 20.16 16.672C19.7547 16.672 19.3813 16.5653 19.04 16.352H19.008C17.2373 15.2213 15.8613 14.0693 14.88 12.896C13.4933 11.232 12.8 9.45067 12.8 7.552C12.8 6.18667 13.1413 4.91733 13.824 3.744C14.4853 2.61333 15.3813 1.70667 16.512 1.024C17.6427 0.341333 18.8587 0 20.16 0ZM11.488 1.984C9.67467 2.368 8.04267 3.14667 6.592 4.32C5.14133 5.49333 4.01067 6.92267 3.2 8.608C2.34667 10.3573 1.92 12.224 1.92 14.208C1.92 14.72 1.952 15.2427 2.016 15.776L2.08 15.744C2.57067 15.488 2.94933 15.3067 3.216 15.2C3.48267 15.0933 3.73867 15.0933 3.984 15.2C4.22933 15.3067 4.4 15.488 4.496 15.744C4.592 16 4.58667 16.256 4.48 16.512C4.37333 16.768 4.19733 16.9493 3.952 17.056C3.70667 17.1627 3.36 17.3227 2.912 17.536L2.656 17.664C2.57067 17.7067 2.48533 17.7387 2.4 17.76C2.89067 19.4667 3.70133 20.9973 4.832 22.352C5.96267 23.7067 7.296 24.7573 8.832 25.504C10.432 26.272 12.1173 26.656 13.888 26.656C15.4667 26.656 16.9813 26.3467 18.432 25.728C19.8187 25.1307 21.0667 24.288 22.176 23.2C21.92 23.0507 21.7653 22.8373 21.712 22.56C21.6587 22.2827 21.7013 22.0267 21.84 21.792C21.9787 21.5573 22.176 21.408 22.432 21.344C22.8373 21.2587 23.2 21.12 23.52 20.928C23.6907 20.8427 23.8613 20.8 24.032 20.8C24.8 19.5413 25.3333 18.176 25.632 16.704C25.6747 16.4267 25.808 16.2133 26.032 16.064C26.256 15.9147 26.496 15.8667 26.752 15.92C27.008 15.9733 27.2107 16.1173 27.36 16.352C27.5093 16.5867 27.552 16.832 27.488 17.088C27.0613 19.2853 26.1973 21.264 24.896 23.024C23.5947 24.784 22.0053 26.1547 20.128 27.136C18.1653 28.16 16.0853 28.672 13.888 28.672C11.3707 28.672 9.03467 28.0107 6.88 26.688C4.78933 25.408 3.12533 23.68 1.888 21.504C0.629333 19.264 0 16.832 0 14.208C0 11.904 0.490667 9.73867 1.472 7.712C2.41067 5.74933 3.728 4.09067 5.424 2.736C7.12 1.38133 9.01333 0.48 11.104 0.032C11.36 -0.032 11.6 0.0106667 11.824 0.16C12.048 0.309333 12.1867 0.522667 12.24 0.8C12.2933 1.07733 12.2453 1.328 12.096 1.552C11.9467 1.776 11.744 1.92 11.488 1.984ZM14.72 7.552C14.72 8.96 15.2533 10.304 16.32 11.584C17.1733 12.5867 18.3893 13.6 19.968 14.624C20.032 14.6453 20.096 14.656 20.16 14.656C20.224 14.656 20.288 14.6453 20.352 14.624C21.9307 13.6213 23.1467 12.608 24 11.584C25.0667 10.304 25.6 8.96 25.6 7.552C25.6 6.57067 25.3547 5.65333 24.864 4.8C24.3733 3.94667 23.7067 3.26933 22.864 2.768C22.0213 2.26667 21.12 2.016 20.16 2.016C19.2 2.016 18.2987 2.26667 17.456 2.768C16.6133 3.26933 15.9467 3.94667 15.456 4.8C14.9653 5.65333 14.72 6.57067 14.72 7.552ZM17.28 7.68C17.28 6.848 17.5627 6.13867 18.128 5.552C18.6933 4.96533 19.3707 4.672 20.16 4.672C20.9493 4.672 21.6267 4.96533 22.192 5.552C22.7573 6.13867 23.04 6.848 23.04 7.68C23.04 8.512 22.7573 9.216 22.192 9.792C21.6267 10.368 20.9493 10.656 20.16 10.656C19.3707 10.656 18.6933 10.368 18.128 9.792C17.5627 9.216 17.28 8.512 17.28 7.68ZM6.752 14.688C7.62667 14.7733 8.53333 15.0293 9.472 15.456C9.70667 15.5627 9.87733 15.744 9.984 16C10.0907 16.256 10.0907 16.512 9.984 16.768C9.87733 17.024 9.70133 17.2 9.456 17.296C9.21067 17.392 8.97067 17.3867 8.736 17.28C7.94667 16.9387 7.22133 16.736 6.56 16.672C6.28267 16.6293 6.064 16.5013 5.904 16.288C5.744 16.0747 5.68 15.8293 5.712 15.552C5.744 15.2747 5.86133 15.0507 6.064 14.88C6.26667 14.7093 6.496 14.6453 6.752 14.688ZM17.6 20.544C18.304 20.864 18.976 21.0987 19.616 21.248C19.872 21.312 20.0693 21.4613 20.208 21.696C20.3467 21.9307 20.3893 22.1813 20.336 22.448C20.2827 22.7147 20.144 22.9227 19.92 23.072C19.696 23.2213 19.4453 23.264 19.168 23.2C18.4213 23.0293 17.632 22.752 16.8 22.368C16.5653 22.2613 16.4 22.08 16.304 21.824C16.208 21.568 16.2133 21.312 16.32 21.056C16.4267 20.8 16.6027 20.624 16.848 20.528C17.0933 20.432 17.344 20.4373 17.6 20.544ZM12.832 17.44C13.0027 17.568 13.248 17.7493 13.568 17.984L14.496 18.688C14.7093 18.8587 14.8373 19.0773 14.88 19.344C14.9227 19.6107 14.8693 19.856 14.72 20.08C14.5707 20.304 14.368 20.4427 14.112 20.496C13.856 20.5493 13.6107 20.5013 13.376 20.352L11.744 19.072C11.5307 18.9227 11.4027 18.7093 11.36 18.432C11.3173 18.1547 11.3707 17.904 11.52 17.68C11.6693 17.456 11.872 17.3227 12.128 17.28C12.384 17.2373 12.6187 17.2907 12.832 17.44ZM20.16 8.672C20.416 8.672 20.64 8.576 20.832 8.384C21.024 8.192 21.12 7.95733 21.12 7.68C21.12 7.40267 21.024 7.16267 20.832 6.96C20.64 6.75733 20.416 6.656 20.16 6.656C19.904 6.656 19.68 6.75733 19.488 6.96C19.296 7.16267 19.2 7.40267 19.2 7.68C19.2 7.95733 19.296 8.192 19.488 8.384C19.68 8.576 19.904 8.672 20.16 8.672Z", fill: "#666666" }))), h("p", { class: "s-bullet-delivery-saved-addresses-empty-title" }, Salla.lang.get("pages.checkout.no_saved_addresses")), h("p", { class: "s-bullet-delivery-saved-addresses-empty-desc" }, Salla.lang.get("pages.checkout.add_address_simplify_shipping")), h("salla-button", { onClick: () => this.handleAddNewAddress(), onKeyUp: () => this.handleAddNewAddress() }, Salla.lang.get("pages.checkout.add_new_address"))));
    }
    /**
     * Save session address (guest intent) to user profile. Returns the newly saved address or null.
     */
    async saveSessionAddressToProfile() {
        const intent = this.getStoredIntent();
        const countryId = getIntentCountryId(intent);
        const cityId = getIntentCityId(intent);
        const districtId = getIntentDistrictId(intent);
        if (!intent || intent.type !== "address" || !countryId || !cityId)
            return null;
        const countryCode = getIntentCountryCode(intent);
        if (isSaudiArabia(countryCode) && !districtId)
            return null;
        const isSA = isSaudiArabia(countryCode);
        const districtName = intent.address_details?.district?.name ?? "";
        const payload = {
            country_id: countryId,
            region_id: getIntentRegionId(intent),
            city_id: cityId,
            district_id: districtId,
            description: districtName,
        };
        if (isSA) {
            payload.local = districtName;
        }
        try {
            const { success, address } = await bulletDeliveryAPI.saveAddressLocation(payload);
            if (!success)
                return null;
            const savedAddress = address ?? null;
            if (savedAddress) {
                this.addressCreated.emit({ address: savedAddress });
            }
            return savedAddress;
        }
        catch (error) {
            console.error("SallaBulletDelivery: Error saving session address", error);
            return null;
        }
    }
    renderSavedAddresses() {
        if (!this.isLoggedIn)
            return null;
        if (this.loadingSavedAddresses) {
            return (h("div", { class: "s-bullet-delivery-addresses-list s-scrollbar" }, [1, 2, 3].map((v) => (h("div", { key: v, class: "s-bullet-delivery-address-item s-bullet-delivery-address-item--skeleton" }, h("salla-skeleton", { class: "s-bullet-delivery-skel-radio", height: "18px", width: "18px" }), h("salla-skeleton", { class: "s-bullet-delivery-skel-map", height: "36px", width: "36px" }), h("div", { class: "s-bullet-delivery-address-content" }, h("div", { class: "s-bullet-delivery-address-lines" }, h("salla-skeleton", { height: "18px", width: "72%" }), h("salla-skeleton", { height: "16px", width: "56%" }))))))));
        }
        const intent = this.getStoredIntent();
        const hasSessionAddress = hasSessionAddressIntent(intent);
        const sessionLine1 = hasSessionAddress && intent?.address_details
            ? [intent.address_details.city?.name, intent.address_details.country?.name]
                .filter(Boolean)
                .join("، ") || ""
            : "";
        const sessionLine2 = hasSessionAddress && intent?.address_details
            ? (intent.address_details.district?.name ?? "").trim()
            : "";
        if (this.savedAddresses.length === 0 && !hasSessionAddress) {
            return this.renderSavedAddressesEmptyState();
        }
        return (h("div", { class: "s-bullet-delivery-addresses-list s-scrollbar" }, hasSessionAddress &&
            this.renderAddressRow({
                key: "session-address",
                line1: sessionLine1,
                line2: sessionLine2,
                selected: this.selectedSessionAddress,
                onClick: () => this.handleSessionAddressSelect(),
            }), this.savedAddresses.map((address) => {
            const builtLine1 = [address.building_number, address.street]
                .filter(Boolean)
                .join("، ");
            const line1 = builtLine1 || address.formatted?.address_one || address.short_address || "";
            const builtLine2 = [
                address.district?.name,
                address.city?.name,
                address.country?.name,
            ]
                .filter(Boolean)
                .join("، ");
            const line2 = (address.formatted?.address_two || builtLine2) ?? "";
            const inCoverage = address.is_in_coverage !== false;
            return this.renderAddressRow({
                key: String(address.id),
                line1,
                line2,
                selected: this.selectedSavedAddress?.id === address.id,
                disabled: !inCoverage,
                onClick: () => inCoverage && this.handleSavedAddressSelect(address),
            });
        })));
    }
    renderAddressRow(options) {
        const { key, line1, line2, selected, disabled = false, onClick } = options;
        return (h("button", { key: key, class: {
                "s-bullet-delivery-address-item": true,
                "s-bullet-delivery-address-item--selected": selected,
                "s-bullet-delivery-address-item--disabled": disabled,
            }, type: "button", onClick: disabled ? undefined : onClick, onKeyDown: (e) => {
                if (e.key === "Enter" || e.key === " ") {
                    e.preventDefault();
                    if (!disabled)
                        onClick();
                }
            } }, h("input", { type: "radio", name: "saved_address", class: "s-bullet-delivery-radio", checked: selected, disabled: disabled, onClick: (e) => e.stopPropagation() }), h("span", { class: "s-bullet-delivery-address-map-icon", innerHTML: MiniMap, "aria-hidden": "true" }), h("div", { class: "s-bullet-delivery-address-content" }, h("div", { class: "s-bullet-delivery-address-lines" }, h("span", { class: "s-bullet-delivery-address-line1" }, line1), h("span", { class: "s-bullet-delivery-address-line2" }, line2)))));
    }
    renderGuestDeliveryForm() {
        const isSA = isSaudiArabia(this.selectedCountry?.code ?? '');
        return [
            this.renderCountrySelect(),
            isSA ? this.renderRegionSelect() : null,
            this.renderCityDistrictSelects(),
        ];
    }
    renderDeliveryTab() {
        return (h("div", { class: {
                "s-bullet-delivery-content": true,
                "s-bullet-delivery-content--active": this.activeTab === "address",
                "s-hidden": this.activeTab !== "address",
            } }, this.isLoggedIn
            ? this.renderSavedAddresses()
            : this.renderGuestDeliveryForm()));
    }
    renderBranchSearch() {
        return (h("div", { class: "s-bullet-delivery-branch-search" }, h("div", { class: "s-bullet-delivery-search-row" }, h("div", { class: "s-bullet-delivery-search s-bullet-delivery-branch-search-wrap" }, h("span", { class: "s-bullet-delivery-search-icon s-bullet-delivery-branch-search-icon", innerHTML: Search, "aria-hidden": "true" }), h("input", { type: "text", class: "s-bullet-delivery-branch-search-input form-input", placeholder: Salla.lang.get("pages.checkout.search_for_city_or_branch"), value: this.branchSearchQuery, onInput: (e) => this.handleBranchSearch(e), autocomplete: "off" })), h("button", { type: "button", class: {
                "s-bullet-delivery-location-btn": true,
                "s-bullet-delivery-location-btn--full": true,
                "s-bullet-delivery-location-btn--loading": this.loadingNearestBranch,
            }, onClick: () => this.handleFindNearestBranch(), disabled: this.loadingNearestBranch }, this.loadingNearestBranch ? (h("span", { class: "s-bullet-delivery-location-icon", "aria-hidden": "true" }, h("salla-skeleton", { height: "18px", width: "18px" }))) : (h("span", { class: "s-bullet-delivery-location-icon", innerHTML: GPS, "aria-hidden": "true" })), h("span", null, Salla.lang.get("pages.checkout.nearest_to_my_location")))), this.locationError && this.activeTab === "branch" && (h("span", { class: "s-bullet-delivery-error" }, this.locationError))));
    }
    renderBranchList() {
        if (this.loadingBranches) {
            return (h("div", { class: "s-bullet-delivery-branches-wrap" }, h("div", { class: "s-bullet-delivery-branches-loading" }, [1, 2, 3, 4].map((v) => (h("div", { key: v, class: "s-bullet-delivery-branch-skeleton" }, h("salla-skeleton", { class: "s-bullet-delivery-branch-skeleton-radio", type: "circle", height: "16px", width: "16px" }), h("div", { class: "s-bullet-delivery-branch-skeleton-icon" }, h("salla-skeleton", { height: "34px", width: "34px" })), h("div", { class: "s-bullet-delivery-branch-skeleton-content" }, h("salla-skeleton", { class: "s-bullet-delivery-branch-skeleton-title", height: "12px", width: "124px" })), h("salla-skeleton", { class: "s-bullet-delivery-branch-skeleton-time", height: "12px", width: "88px" }), h("div", { class: "s-bullet-delivery-branch-skeleton-map" }, h("salla-skeleton", { height: "32px", width: "32px" }))))))));
        }
        if (this.filteredBranches.length === 0) {
            return (h("salla-placeholder", { alignment: "center", class: "s-bullet-delivery-placeholder" }, h("span", { slot: "title" }, Salla.lang.get("pages.checkout.no_pickup_branches_found"))));
        }
        return (h("div", { class: "s-bullet-delivery-branches-wrap" }, h("ul", { class: "s-bullet-delivery-branches-list s-scrollbar" }, this.filteredBranches.map((branch) => (h("li", { key: branch.id, class: {
                "s-bullet-delivery-branch-item": true,
                "s-bullet-delivery-branch-item--selected": this.selectedBranch?.id === branch.id,
                "s-bullet-delivery-branch-item--disabled": branch.is_open === false,
            }, tabIndex: branch.is_open === false ? -1 : 0, role: "option", "aria-disabled": branch.is_open === false, onClick: () => branch.is_open !== false && this.handleBranchSelect(branch), onKeyDown: (e) => {
                if (e.key === "Enter" || e.key === " ") {
                    e.preventDefault();
                    if (branch.is_open !== false)
                        this.handleBranchSelect(branch);
                }
            } }, h("input", { type: "radio", name: "branch", class: "s-bullet-delivery-radio", checked: this.selectedBranch?.id === branch.id, disabled: branch.is_open === false }), h("span", { class: "s-bullet-delivery-branch-icon", "aria-hidden": "true" }, h("span", { innerHTML: Store })), h("div", { class: "s-bullet-delivery-branch-info" }, h("span", { class: "s-bullet-delivery-branch-name" }, branch.name), branch.preparation_time ? (h("span", { class: "s-bullet-delivery-branch-prep" }, `${Salla.lang.get("pages.checkout.processing_time")}: ${branch.preparation_time}`)) : null), (() => {
            const slot = getBranchFirstSlot(branch.working_hours);
            return slot ? (h("span", { class: "s-bullet-delivery-branch-time" }, formatWorkingHoursDisplay(slot.from, slot.to, Salla.config.get("user.language_code") ||
                "ar", Salla.lang.get("pages.checkout.until")))) : null;
        })(), branch.location?.lat != null && branch.location?.lng != null && (h("a", { href: `https://www.google.com/maps?q=${branch.location.lat},${branch.location.lng}`, target: "_blank", rel: "noopener noreferrer", class: "s-bullet-delivery-branch-map-link", title: Salla.lang.get("common.elements.open_in_google_maps"), onClick: (e) => e.stopPropagation() }, h("span", { class: "s-bullet-delivery-branch-map-link-icon", innerHTML: GetDirections.replace(/mask0_25437_34440/g, `mask0_branch_${branch.id}`), "aria-hidden": "true" }), h("span", { class: "sr-only" }, Salla.lang.get("common.elements.open_in_google_maps"))))))))));
    }
    renderPickupTab() {
        return (h("div", { class: {
                "s-bullet-delivery-content": true,
                "s-bullet-delivery-content--active": this.activeTab === "branch",
                "s-hidden": this.activeTab !== "branch",
            } }, this.renderCountrySelect(), this.renderBranchSearch(), this.renderBranchList()));
    }
    /** Add-address form: same fields as guest form (country, region, city, district) only. */
    renderAddAddressForm() {
        const title = Salla.lang.get("pages.checkout.add_new_address");
        const isSA = isSaudiArabia(this.selectedCountry?.code ?? '');
        const canSubmit = this.selectedCountry &&
            this.selectedCity &&
            (!isSA || this.selectedRegion) &&
            (!isSA ||
                !!this.selectedDistrict ||
                !!(this.districtName && this.districtName.trim().length > 0));
        const submitLabel = this.savingAddress
            ? Salla.lang.get("pages.checkout.loading")
            : Salla.lang.get("pages.checkout.confirm_address");
        const hasAddressesToGoBack = this.savedAddresses.length > 0 || hasSessionAddressIntent(this.getStoredIntent());
        return (h("div", { class: "s-bullet-delivery-add-address" }, h("div", { class: "s-bullet-delivery-add-address-header" }, hasAddressesToGoBack ? (h("button", { type: "button", class: "s-bullet-delivery-add-address-title", onClick: () => this.handleBackToAddressList(), onKeyDown: (e) => e.key === "Enter" && this.handleBackToAddressList() }, h("span", { innerHTML: this.isRTL ? ArrowRight : ArrowLeft, "aria-hidden": "true" }), h("span", { class: "s-bullet-delivery-add-address-title-text" }, title))) : (h("span", { class: "s-bullet-delivery-add-address-title" }, h("span", { class: "s-bullet-delivery-add-address-title-text" }, title)))), h("form", { class: "s-bullet-delivery-add-address-form", onSubmit: (e) => this.handleSubmitAddAddress(e) }, this.renderGuestDeliveryForm(), h("div", { class: "s-bullet-delivery-form-actions s-bullet-delivery-form-actions--single" }, h("salla-button", { type: "submit", loading: this.savingAddress, disabled: !canSubmit || this.savingAddress, class: "s-bullet-delivery-add-address-submit" }, submitLabel)))));
    }
    renderFooter() {
        const showAddAddressInFooter = this.activeTab === "address" && this.isLoggedIn;
        return (h("div", { class: "s-bullet-delivery-footer" }, h("salla-button", { ref: (btn) => {
                this.confirmBtn = btn;
            }, disabled: this.isConfirmDisabled(), onClick: () => this.handleConfirm(), "loader-position": "center", width: "wide" }, this.activeTab === "branch"
            ? Salla.lang.get("pages.checkout.confirm_receipt_from_the_branch")
            : Salla.lang.get("pages.checkout.confirm_address")), showAddAddressInFooter && (h("salla-button", { onClick: () => this.handleAddNewAddress(), width: "wide", shape: "link" }, Salla.lang.get("pages.checkout.add_new_address"))), !this.isLoggedIn && (h("salla-button", { shape: "link", onClick: this.handleLogin }, Salla.lang.get("pages.checkout.login_to_use_saved_addresses")))));
    }
    renderMainView() {
        const isAddressEmptyState = this.isLoggedIn &&
            this.activeTab === "address" &&
            this.savedAddresses.length === 0 &&
            !hasSessionAddressIntent(this.getStoredIntent());
        const activeTabView = this.activeTab === "branch" && this.supportsPickup
            ? this.renderPickupTab()
            : this.renderDeliveryTab();
        return (h("div", null, h("div", { class: "s-bullet-delivery-header" }, h("h2", { class: "s-bullet-delivery-title" }, this.activeTab === 'address' ? Salla.lang.get('blocks.home.add_address_for_order_delivery') : Salla.lang.get('blocks.home.how_prefer_to_receive_order')), h("p", { class: "s-bullet-delivery-subtitle" }, this.activeTab === 'address' ? Salla.lang.get('blocks.home.products_available_for_delivery_shown_while_shopping') : Salla.lang.get('blocks.home.products_available_for_delivery_or_pickup_shown_while_shopping'))), this.renderTabs(), this.showCartWillBeClearedBanner &&
            this.renderAlert(Salla.lang.get("blocks.scope.empty_cart_warning")), this.allocationOutOfCoverageMessage &&
            this.renderAllocationOutOfCoverageAlert(), activeTabView, !isAddressEmptyState && this.renderFooter()));
    }
    handleAfterAddToCart() {
        if (this.openingType !== "after_add_to_cart")
            return;
        const canOpenForIncompleteIntent = this.shouldPromptIncompleteIntentThisSession();
        if (this.hasBeenShownThisSession() && !canOpenForIncompleteIntent)
            return;
        if (this.modal?.hasAttribute?.("visible"))
            return;
        if (canOpenForIncompleteIntent) {
            this.markIncompleteIntentPrompted();
        }
        this.open();
    }
    overrideScopeSwitchUI() {
        const intent = this.getStoredIntent();
        const btn = document.querySelector('[onclick*="scopes"]');
        if (!btn)
            return;
        const hasIntentWithType = !!intent && (intent.type === "address" || intent.type === "branch");
        if (!hasIntentWithType) {
            btn.style.display = "none";
            btn.onclick = () => this.open();
            return;
        }
        const trunc = (s, max) => s && s.length > max ? `${s.slice(0, max)}...` : (s ?? "");
        const label = intent.type === "branch"
            ? `${Salla.lang.get("mobile_app.strings.pickup")} ${Salla.lang.get("common.elements.from")} ${trunc(intent.branch_details?.name, 20)}`
            : `${Salla.lang.get("mobile_app.strings.delivery")} ${Salla.lang.get("common.elements.to")} ${trunc(intent.address_details?.city?.name, 10)}`;
        btn.style.display = "inline-flex";
        btn.onclick = () => this.open();
        const span = btn.querySelector('span:not([class*="sicon"]):not([class*="icon"])');
        if (span) {
            span.textContent = label;
        }
        else {
            const textNode = Array.from(btn.childNodes).find((n) => n.nodeType === Node.TEXT_NODE && n.textContent?.trim());
            if (textNode)
                textNode.textContent = ` ${label}`;
        }
    }
    async componentWillLoad() {
        await Salla.onReady();
        try {
            this.overrideScopeSwitchUI();
            this.cartSubmittingHandler = async () => {
                if (this.pendingCartSubmitPromise) {
                    await this.pendingCartSubmitPromise;
                    return;
                }
                // Logged-in users with a complete intent can continue checkout without re-prompting.
                if (this.hasCompleteIntentForLoggedInUser()) {
                    return;
                }
                this.cartSubmitConfirmationPending = true;
                this.pendingCartSubmitPromise = new Promise((resolve) => {
                    this.pendingCartSubmitResolver = resolve;
                    if (this.isGuestUser()) {
                        Salla.auth.setCanRedirect(false);
                        Salla.event.dispatch("login::open", {
                            withoutReload: true,
                            source: "cart-submit",
                        });
                        return;
                    }
                    this.open();
                });
                await this.pendingCartSubmitPromise;
            };
            Salla.cart.event.onSubmitting(this.cartSubmittingHandler);
        }
        catch (e) {
            console.warn("SallaBulletDelivery: overrideScopeSwitchUI failed", e);
        }
        Salla.event.on("salla::bullet-delivery.modal.open.requested", this.bulletDeliveryOpenHandler);
        this.closeHandler = this.close.bind(this);
        Salla.event.on("salla::bullet-delivery.modal.close.requested", this.closeHandler);
        this.isRTL = Salla.config.get("theme.is_rtl");
        this.authLoggedInHandler = () => {
            if (this.cartSubmitConfirmationPending) {
                Salla.event.dispatch("login::close");
                if (this.hasCompleteIntentForLoggedInUser()) {
                    this.resolvePendingCartSubmit();
                    return;
                }
                if (!this.modal?.hasAttribute?.("visible")) {
                    this.open();
                }
                return;
            }
            // Always prompt after login when intent is incomplete, regardless of prior prompted flags.
            if (!this.hasIncompleteUserAddressIntent())
                return;
            if (this.modal?.hasAttribute?.("visible"))
                return;
            this.open();
        };
        Salla.event.on("auth::logged.in", this.authLoggedInHandler);
        this.authLoggedOutHandler = () => {
            this.clearBulletDeliveryStoredData();
        };
        Salla.event.on("auth::logged.out", this.authLoggedOutHandler);
        this.loginClosedHandler = () => {
            // Guest cart-submit flow opens login first; if login is dismissed, unblock submit gate.
            if (!this.cartSubmitConfirmationPending || !this.isGuestUser())
                return;
            if (this.hasCompleteIntentForLoggedInUser())
                return;
            this.resolvePendingCartSubmit();
        };
        Salla.event.on("salla-login::closed", this.loginClosedHandler);
        // Listen for add-to-cart events for 'after_add_to_cart' opening strategy (after salla is ready)
        this.cartItemAddedHandler = () => this.handleAfterAddToCart();
        if (typeof Salla.cart?.event?.onItemAdded === "function") {
            this.useCartEventApi = true;
            Salla.cart.event.onItemAdded(this.cartItemAddedHandler);
        }
        else {
            Salla.event.on(this.cartItemAddedEvent, this.cartItemAddedHandler);
        }
    }
    render() {
        if (this.isMobileApp)
            return null;
        return (h(Host, { class: "s-bullet-delivery" }, h("salla-modal", { ref: (modal) => {
                this.modal = modal;
            }, isClosable: !this.isRequired && !this.shouldForceNonClosable(), class: "s-bullet-delivery-modal", width: "sm" }, h("div", { class: "s-bullet-delivery-inner" }, this.viewMode === "main" && this.renderMainView(), this.viewMode === "add-address" && this.renderAddAddressForm()))));
    }
    componentDidLoad() {
        // Mark component as ready
        this.componentReady = true;
        if (this.isMobileApp) {
            // Ask the mobile app to render its native delivery sheet (replacement for our modal).
            if (!this.hasBeenShownThisSession()) {
                Salla.event.dispatch('salla::bullet-delivery.open-sheet');
            }
            // When the user confirms inside the mobile sheet, mobile dispatches
            // `salla::bullet-delivery.select` with a payload equivalent to what
            // `handleConfirm()` produces on desktop. Apply the same side-effects.
            this.bulletDeliveryMobileSelectHandler = (raw) => {
                const payload = this.extractMobileSelectPayload(raw);
                if (!payload) {
                    console.warn("SallaBulletDelivery: received empty mobile select payload", raw);
                    return;
                }
                this.applyMobileBulletDeliverySelection(payload);
            };
            Salla.event.on("salla::bullet-delivery.select", this.bulletDeliveryMobileSelectHandler);
            // Skip desktop-only initialisation: the auto-open strategy switch and the
            // cart:items.start hook mount are both no-ops or actively harmful in the
            // mobile webview (no modal exists, and we'd inject a non-functional HTML
            // pill into the native cart UI).
            return;
        }
        // Handle pending open request (if event was emitted before component was ready)
        if (this.pendingOpen) {
            this.pendingOpen = false;
            this.open();
            return;
        }
        // Strategy-based auto-open logic
        switch (this.openingType) {
            case "first_visit":
                // Open once per session when component mounts (per-session behaviour)
                if (!this.hasBeenShownThisSession()) {
                    this.open();
                }
                else if (this.shouldPromptIncompleteIntentThisSession()) {
                    this.markIncompleteIntentPrompted();
                    this.open();
                }
                break;
            case "on_cart_click":
                // Open automatically when user is on the cart page
                if (Salla.url.is_page("cart")) {
                    const shown = this.getShownStorage().get(this.sessionShownKey) === true;
                    if (!shown) {
                        this.open();
                    }
                    else if (this.shouldPromptIncompleteIntentThisSession()) {
                        this.markIncompleteIntentPrompted();
                        this.open();
                    }
                }
                break;
            case "after_add_to_cart":
                // Handled reactively via cart::item.added event listener
                break;
            default:
                break;
        }
        // Mount cart view into cart.items.start hook
        const cartViewEl = this.createCartViewElement();
        if (cartViewEl && typeof salla?.hooks?.mount === "function") {
            Salla.hooks.mount("cart:items.start", cartViewEl).catch(() => {
                // Hook may not exist on this page; ignore
            });
        }
    }
    disconnectedCallback() {
        this.componentReady = false;
        Salla.event.off("salla::bullet-delivery.modal.open.requested", this.bulletDeliveryOpenHandler);
        if (this.closeHandler) {
            Salla.event.off("salla::bullet-delivery.modal.close.requested", this.closeHandler);
            this.closeHandler = null;
        }
        if (this.cartItemAddedHandler) {
            if (this.useCartEventApi && typeof Salla.cart?.event?.offItemAdded === "function") {
                Salla.cart.event.offItemAdded(this.cartItemAddedHandler);
            }
            else {
                Salla.event.off(this.cartItemAddedEvent, this.cartItemAddedHandler);
            }
            this.cartItemAddedHandler = null;
        }
        if (this.cartSubmittingHandler) {
            if (typeof Salla.cart?.event?.offSubmitting === "function") {
                Salla.cart.event.offSubmitting(this.cartSubmittingHandler);
            }
            else {
                Salla.event.off("cart::submitting", this.cartSubmittingHandler);
            }
            this.cartSubmittingHandler = null;
        }
        if (this.authLoggedInHandler) {
            Salla.event.off("auth::logged.in", this.authLoggedInHandler);
            this.authLoggedInHandler = null;
        }
        if (this.authLoggedOutHandler) {
            Salla.event.off("auth::logged.out", this.authLoggedOutHandler);
            this.authLoggedOutHandler = null;
        }
        if (this.loginClosedHandler) {
            Salla.event.off("salla-login::closed", this.loginClosedHandler);
            this.loginClosedHandler = null;
        }
        if (this.bulletDeliveryMobileSelectHandler) {
            Salla.event.off("salla::bullet-delivery.select", this.bulletDeliveryMobileSelectHandler);
            this.bulletDeliveryMobileSelectHandler = null;
        }
    }
    static get is() { return "salla-bullet-delivery"; }
    static get originalStyleUrls() {
        return {
            "$": ["salla-bullet-delivery.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["salla-bullet-delivery.css"]
        };
    }
    static get states() {
        return {
            "activeTab": {},
            "isLoggedIn": {},
            "viewMode": {},
            "countries": {},
            "regions": {},
            "cities": {},
            "districts": {},
            "loadingRegions": {},
            "selectedCountry": {},
            "selectedRegion": {},
            "selectedCity": {},
            "selectedDistrict": {},
            "districtName": {},
            "savedAddresses": {},
            "selectedSavedAddress": {},
            "selectedSessionAddress": {},
            "branches": {},
            "filteredBranches": {},
            "selectedBranch": {},
            "branchSearchQuery": {},
            "loadingCountries": {},
            "loadingCities": {},
            "loadingDistricts": {},
            "loadingBranches": {},
            "loadingNearestBranch": {},
            "locationError": {},
            "savingAddress": {},
            "loadingSavedAddresses": {},
            "showCartWillBeClearedBanner": {},
            "countrySearchQuery": {},
            "regionSearchQuery": {},
            "citySearchQuery": {},
            "districtSearchQuery": {},
            "searchingCountries": {},
            "searchingRegions": {},
            "searchingCities": {},
            "searchingDistricts": {},
            "displayedCountries": {},
            "displayedRegions": {},
            "displayedCities": {},
            "displayedDistricts": {},
            "allocationOutOfCoverageMessage": {},
            "newAddressForm": {}
        };
    }
    static get events() {
        return [{
                "method": "bulletDeliveryConfirmed",
                "name": "bulletDeliveryConfirmed",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the user confirms their selection"
                },
                "complexType": {
                    "original": "BulletDeliveryConfirmedEvent",
                    "resolved": "BulletDeliveryConfirmedEvent",
                    "references": {
                        "BulletDeliveryConfirmedEvent": {
                            "location": "import",
                            "path": "./interfaces",
                            "id": "src/components/salla-bullet-delivery/interfaces.ts::BulletDeliveryConfirmedEvent"
                        }
                    }
                }
            }, {
                "method": "bulletDeliveryClosed",
                "name": "bulletDeliveryClosed",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the modal is closed"
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }, {
                "method": "addressCreated",
                "name": "addressCreated",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when a new address is created"
                },
                "complexType": {
                    "original": "AddressCreatedEvent",
                    "resolved": "AddressCreatedEvent",
                    "references": {
                        "AddressCreatedEvent": {
                            "location": "import",
                            "path": "./interfaces",
                            "id": "src/components/salla-bullet-delivery/interfaces.ts::AddressCreatedEvent"
                        }
                    }
                }
            }, {
                "method": "headerContextUpdate",
                "name": "headerContextUpdate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted to sync with the global header (Delivering to: [location])"
                },
                "complexType": {
                    "original": "HeaderContextUpdateEvent",
                    "resolved": "HeaderContextUpdateEvent",
                    "references": {
                        "HeaderContextUpdateEvent": {
                            "location": "import",
                            "path": "./interfaces",
                            "id": "src/components/salla-bullet-delivery/interfaces.ts::HeaderContextUpdateEvent"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "open": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Opens the bullet delivery modal",
                    "tags": []
                }
            },
            "close": {
                "complexType": {
                    "signature": "() => Promise<HTMLElement>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLElement": {
                            "location": "global",
                            "id": "global::HTMLElement"
                        }
                    },
                    "return": "Promise<HTMLElement>"
                },
                "docs": {
                    "text": "Closes the bullet delivery modal",
                    "tags": []
                }
            }
        };
    }
}
/**
 * SA add-address view: 'confirmed' = selected address box + description + confirm, 'full' = all form fields (after Edit).
 */
// Unified form state (guest and add address)
SallaBulletDelivery.INITIAL_ADDRESS_FORM = {
    country_id: 0,
    is_default: false,
    city_id: undefined,
    district_id: undefined,
    street: undefined,
    building_number: undefined,
    additional_number: undefined,
    postal_code: undefined,
    description: undefined,
};
SallaBulletDelivery.DROPDOWN_SEARCH_DEBOUNCE_MS = 400;
SallaBulletDelivery.DROPDOWN_SEARCH_MIN_CHARS = 2;