const Cookies = require('js-cookie');

function serializeFormData(obj, prefix = '') {
    const str = [];
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            const value = obj[key];
            const newKey = prefix ? `${prefix}[${key}]` : key;
            
            if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof File) && !(value instanceof Blob)) {
                // Рекурсивно обрабатываем вложенные объекты
                str.push(serializeFormData(value, newKey));
            } else if (Array.isArray(value)) {
                // Обрабатываем массивы
                value.forEach((item, index) => {
                    if (typeof item === 'object' && item !== null && !(item instanceof File) && !(item instanceof Blob)) {
                        str.push(serializeFormData(item, `${newKey}[${index}]`));
                    } else {
                        str.push(encodeURIComponent(`${newKey}[${index}]`) + '=' + encodeURIComponent(item));
                    }
                });
            } else {
                str.push(encodeURIComponent(newKey) + '=' + encodeURIComponent(value));
            }
        }
    }
    return str.join('&');
}

function sendRequest(data, url, method = "POST", dataType = "json", withCredentials = true, contentType = null) {
    return new Promise(async (resolve, reject) => {
        try {
            const methodUpper = method.toUpperCase();
            const isGetOrHead = methodUpper === "GET" || methodUpper === "HEAD";

            // Для GET/HEAD перемещаем данные в URL
            if (isGetOrHead && data) {
                const params = new URLSearchParams(data);
                url = `${url}${url.includes('?') ? '&' : '?'}${params}`;
            }

            // Автоматическое определение content-type для не-GET запросов
            let finalContentType = contentType;
            if (!finalContentType && !isGetOrHead) {
                finalContentType = "application/x-www-form-urlencoded";
                if (data && Object.values(data).some(value => value instanceof File || value instanceof Blob)) {
                    finalContentType = "multipart/form-data";
                }
            }

            let body = null;
            let headers = {};

            // Подготовка тела только для не-GET запросов
            if (!isGetOrHead && data) {
                switch (finalContentType) {
                    case "application/json":
                        body = JSON.stringify(data);
                        headers["Content-Type"] = "application/json";
                        break;

                    case "multipart/form-data":
                        body = new FormData();
                        Object.entries(data).forEach(([key, value]) => {
                            body.append(key, value);
                        });
                        break;

                    default:
                        // Используем правильную сериализацию для вложенных объектов
                        body = serializeFormData(data);
                        headers["Content-Type"] = "application/x-www-form-urlencoded";
                }
            }

            const response = await fetch(url, {
                method: methodUpper,
                headers: headers,
                credentials: withCredentials ? "include" : "same-origin",
                body: body
            });

            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${await response.text()}`);
            }

            const responseData = await response[dataType]();
            resolve(responseData);

        } catch (error) {
            reject(error);
        }
    });
}

function isMobile() {
    if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) {
        return true;
    }

    return false;
}

function getCityId(address) {
    const cityMap = new Map([
        ['Волгоград', 96],
        ['Воронеж', 98],
        ['Краснодар', 3018],
        ['Саратов', 94]
    ]);

    for (const [cityName, cityId] of cityMap) {
        if (address.includes(cityName)) {
            return cityId;
        }
    }

    return null;
}

function getCityCRM(region) {
    switch (region) {
        case '92': return 96;    // Волгоград
        case '93': return 98;    // Воронеж
        case '94': return 3018;  // Краснодар
        default: return 94;      // Саратов
    }
}

function getLicensePersonLink() {
    if (/cabinet\.sovamed\.ru/m.test(location.hostname) || /cabinet\.wmtmed\.ru/m.test(location.hostname)) {
        return 'https://cabinet.sovamed.ru/docs/soglasie-cabinet.pdf';
    }

    return 'https://cabinet.sovamed.ru/docs/soglasie-site.pdf';
}

function getLicenseLink(region) {
    switch (region) {
        case '92': // Волгоград
            return 'https://volgograd.sovamed.ru/o-sove/dokumenty-i-licenzii/politika-konfidencialnosti/';

        case '93': // Воронеж
            return 'https://voronezh.sovamed.ru/o-sove/dokumenty-i-licenzii/politika-konfidencialnosti/';

        case '94': // Краснодар
            return 'https://wmtmed.ru/about/confidentiality_policy.php';

        case '95': // Совенок
            return 'https://sovenok.sovamed.ru/o-sove/dokumenty-i-licenzii/politika-konfidencialnosti/';

        case '96': // Комфорт
            return 'https://sovamed.ru/docs/comfort_politika.pdf';

        default: // Саратов
            return 'https://sovamed.ru/o-sove/dokumenty-i-licenzii/politika-konfidencialnosti/';
    }
}

function renderCapcha(wrap) {
    const elem = document.getElementById('smart-captcha');

    if (elem) {
        elem.parentNode.removeChild(elem);
    }

    wrap.innerHTML = '';
    var recaptcha = document.createElement('div');
    recaptcha.id = "smart-captcha";
    recaptcha.dataset.controller = "smartCaptcha";
    wrap.append(recaptcha);

    var validRecaptcha = document.createElement('div');
    validRecaptcha.classList = "msg-valid valid-captcha";
    wrap.append(validRecaptcha);

    return recaptcha;
}

function countDown(options) {
    var timer,
    instance = this,
    seconds = options.seconds || 10,
    updateStatus = options.onUpdateStatus || function () {},
    counterEnd = options.onCounterEnd || function () {};

    function decrementCounter() {
        updateStatus(seconds);

        if (seconds === 0) {
            counterEnd();
            instance.stop();
        }

        seconds--;
    }

    this.start = function () {
        clearInterval(timer);
        timer = 0;
        seconds = options.seconds;
        timer = setInterval(decrementCounter, 1000);
    };

    this.stop = function () {
        clearInterval(timer);
    };
}

function getApiHostname() {
    if (/sovamed\.ru/m.test(location.hostname)) {
        return 'https://api.sovamed.ru';
    }
    
    return 'https://api.wmtmed.ru';
}

function getHostname() {   
    if (/sovamed\.ru/m.test(location.hostname)) {
        return 'https://cabinet.sovamed.ru';
    }
    
    return 'https://cabinet.wmtmed.ru';
}

function getRegionIdByHost() {
    switch (location.host) {
        case 'volgograd.sovamed.ru':
            // Волгоград
            var regionId = 92;
        break;

        case 'voronezh.sovamed.ru':
            // Воронеж
            var regionId = 93;
        break;

        case 'sovenok.sovamed.ru':
            // Совенок
            var regionId = 95;
        break;

        case 'comfort.sovamed.ru':
            // Совенок
            var regionId = 96;
        break;

        case 'wmtmed.ru':
            // Краснодар
            var regionId = 94;
        break;

        default:
            // Саратов
            var regionId = 91;
        break;
    };

    return regionId;
}

const SESSION_ID_PARAM = '_ct_session_id';

function readSessionIdCookie() {
    if (typeof document === 'undefined') {
        return null;
    }
    const v = Cookies.get(SESSION_ID_PARAM);
    if (v == null || String(v).trim() === '') {
        return null;
    }
    return String(v).trim();
}

/**
 * Если в query есть sessionId — пишет session-cookie (до закрытия браузера) и убирает параметр из URL.
 */
function syncSessionIdFromUrl() {
    if (typeof window === 'undefined' || !window.location) {
        return;
    }
    const url = new URL(window.location.href);
    const raw = url.searchParams.get(SESSION_ID_PARAM);
    if (raw === null) {
        return;
    }
    const value = String(raw).trim();
    if (!value) {
        url.searchParams.delete(SESSION_ID_PARAM);
        const next = url.pathname + url.search + url.hash;
        if (next !== window.location.pathname + window.location.search + window.location.hash) {
            window.location.replace(next);
        }
        return;
    }
    const secure = window.location.protocol === 'https:' ? '; Secure' : '';
    document.cookie = `${SESSION_ID_PARAM}=${encodeURIComponent(value)}; path=/; SameSite=Lax${secure}`;
    url.searchParams.delete(SESSION_ID_PARAM);
    window.location.replace(url.pathname + url.search + url.hash);
}

function addAlert(msg, alertSystem, id, color = 'alert-danger') {
    var alert = document.createElement('div');
    alert.id = id;
    alert.classList = 'alert alert-dismissible fade show';
    alert.classList.add(color);
    alert.setAttribute('role', 'alert');

    var divMsg = document.createElement('div');
    divMsg.classList = 'alert-msg';
    divMsg.innerHTML = msg;
    alert.append(divMsg);

    alertSystem.prepend(alert);
}

function getSessionId() {
    const fromCt = window.ct?.('calltracking_params')?.[0]?.sessionId;
    if (fromCt != null && String(fromCt).trim() !== '') {
        return String(fromCt).trim();
    }

    const fromCookie = readSessionIdCookie();
    if (fromCookie) {
        return fromCookie;
    }

    return null;
}

function addUrlParam(url, param, value) {
    const urlObj = new URL(url);

    if (!urlObj.searchParams.has(param)) {
        urlObj.searchParams.set(param, value);
    }
    
    return urlObj.toString();
}

module.exports = {
    addUrlParam: addUrlParam,
    getSessionId: getSessionId,
    syncSessionIdFromUrl: syncSessionIdFromUrl,
    addAlert: addAlert,
    getRegionIdByHost: getRegionIdByHost,
    getApiHostname : getApiHostname,
    getHostname: getHostname,
    countDown: countDown,
    isMobile: isMobile,
    sendRequest: sendRequest,
    getLicensePersonLink: getLicensePersonLink,
    getLicenseLink: getLicenseLink,
    getCityCRM: getCityCRM,
    getCityId: getCityId,
    renderCapcha: renderCapcha
};