/**
 * This file handles the hero-live-section and live-quickaccess functionality.
 */
import { onPageLoadComplete } from '@nimius/event-utility';
import { getCookie, setCookie } from '../utils/cookie-utility.js';
import { weatherIconMap } from '../utils/weather-icon-map.js';

let skiAreaData = null;
let weatherData = null;

const fetchChannelContext = async () => {
    // Fetch channelContext to get toursprung apikey
    try {
        let channelContext = null;
        const url = `https://mein.toubiz.de/api/v1/channel/currentContext`;
        const randomId = Math.random().toString(26).substr(2);
        const apiToken = document.querySelector('[data-api-v2-article-key]')
            ?.getAttribute('data-api-v2-article-key') || '';
        const correlationId = `website-plus-${randomId}`;
        const bearer = `Bearer ${apiToken}`;

        if (!apiToken) {
            console.error('No Toubiz Api V2 Article key configured');

            return;
        }

        const options = {
            method: 'GET',
            headers: {
                'X-Toubiz-Correlation-Id': correlationId,
                'X-Toubiz-Referrer': location.href,
                'Content-Type': 'application/json',
                'Accept': 'application/json',
                'Authorization': bearer,
            },
        };

        const response = await fetch(url, options);

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

        channelContext = await response.json();

        return channelContext;
    } catch (error) {
        console.error('Fetch error:', error);
    }
};

const getToursprungApiKey = async () => {
    if (getCookie('toursprungApiKey')) {
        return getCookie('toursprungApiKey');
    } else {
        const channelContext = await fetchChannelContext();

        /* eslint-disable no-underscore-dangle */
        setCookie('toursprungApiKey', channelContext?._attributes?.channel?.toursprung?.apiKey);

        return channelContext?._attributes?.channel?.toursprung?.apiKey;
        /* eslint-enable no-underscore-dangle */
    }
};

const weatherApiFetch = async (lat, lon) => {
    /**
     * Use the 'toubiz' api key for development.
     *
     * let apiToken = 'toubiz';
     */
    let apiToken = await (getToursprungApiKey() || 'toubiz');
    const hours = 4;
    const url =
        `https://weather.maptoolkit.net/forecast/icon?api_key=${apiToken}&lat=${lat}&lng=${lon}&forecast=${hours}`;

    const response = await fetch(url, {
        method: 'GET',
    });

    if (response.status !== 200) {
        weatherData = null;

        throw new Error('Failed to fetch weather data');
    }

    weatherData = await response.json();

    return weatherData;
};

const skiAreaFetch = async (toubizId) => {
    const apiToken = document.querySelector('[data-api-v2-article-key]')
        ?.getAttribute('data-api-v2-article-key') || '';

    if (!apiToken) {
        console.error('No Toubiz Api V2 Article key configured');

        return;
    }

    try {
        const url = `https://mein.toubiz.de/api/v2/public/skiArea/${toubizId}?language=de`;

        const randomId = Math.random().toString(26).substr(2);
        const correlationId = `website-plus-${randomId}`;
        const bearer = `Bearer ${apiToken}`;

        const options = {
            method: 'GET',
            headers: {
                'X-Toubiz-Correlation-Id': correlationId,
                'X-Toubiz-Referrer': location.href,
                'Content-Type': 'application/json',
                'Accept': 'application/json',
                'Authorization': bearer,
            },
        };

        const response = await fetch(url, options);

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

        skiAreaData = await response.json();

        return skiAreaData;
    } catch (error) {
        console.error('Fetch error:', error);
    }
};

// Update DOM functions
const setWeatherData = () => {
    if (!weatherData) {
        return;
    }

    const weatherDataFields = document.querySelectorAll('[data-live-weather-degrees]') || [];
    const weatherIconFields = document.querySelectorAll('[data-live-weather-icon]') || [];
    const todayData = weatherData?.[ 0 ];

    const weatherIcon = () => {
        const weatherCode = todayData?.weather_code?.toString() ?? 'na';

        if (!weatherIconMap.has(weatherCode)) {
            return weatherIconMap.get('na');
        }

        return weatherIconMap.get(weatherCode);
    };

    weatherDataFields.forEach((field) => {
        field.textContent = `${Math.round(todayData?.temperature)} °C`;
    });
    weatherIconFields.forEach((field) => {
        field.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', `#${weatherIcon()}`);
    });
};

const setSkiAreaData = () => {
    if (!skiAreaData) {
        return;
    }

    const statistics = skiAreaData.payload?.statistics || [];
    const snowReports = skiAreaData.payload?.snowReports || [];
    const snowTransportationOpen = statistics.filter(statistic => statistic.type === 'snowTransportationOpen');
    const snowDepthMin = snowReports[ 0 ].depthMin;
    const snowDepthTop = snowReports[ 0 ].depthMax;
    const snowDepthOutput = snowDepthMin === snowDepthTop
        ? `${snowDepthMin} cm`
        : `${snowDepthMin} - ${snowDepthTop} cm`;

    const snowDepthFields = document.querySelectorAll('[data-live-snow-depth]') || [];
    const snowTransportationOpenFields = document.querySelectorAll('[data-live-lifts-open]') || [];

    snowDepthFields.forEach((field) => {
        field.textContent = snowDepthOutput;
    });

    snowTransportationOpenFields.forEach((field) => {
        field.textContent = `${snowTransportationOpen[ 0 ].number}/${snowTransportationOpen[ 0 ].total}`;
    });
};

const initLiveQuickaccessVisibility = (heroLiveSection, liveQuickaccess) => {
    const inactiveClass = 'c-live-quickaccess--inactive';

    if (!liveQuickaccess) {
        return;
    }
    if (!heroLiveSection) {
        liveQuickaccess.classList.remove(inactiveClass);
        return;
    }

    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (!entry.isIntersecting) {
                liveQuickaccess.classList.remove(inactiveClass);
            } else {
                liveQuickaccess.classList.add(inactiveClass);
            }
        });
    }, {
        root: null,
        threshold: 0.1,
    });

    observer.observe(heroLiveSection);
};

// eslint-disable-next-line max-statements
onPageLoadComplete(async () => {
    const heroLiveSection = document.querySelector('[data-hero-live-section]');
    const liveQuickaccess = document.querySelector('[data-live-quickaccess]');
    const liveSectionContent = document.querySelectorAll('[data-live-section-content]');
    const liveSectionLoader = document.querySelectorAll('[data-live-section-loader]');

    if (!heroLiveSection && !liveQuickaccess) {
        return;
    }

    initLiveQuickaccessVisibility(heroLiveSection, liveQuickaccess);

    const promises = [];
    const skiAreaToubizId = document.querySelector('[data-live-ski-area-toubiz-id]');
    const liveWeatherLat = document.querySelector('[data-live-weather-lat]');
    const liveWeatherLon = document.querySelector('[data-live-weather-lon]');

    if (liveWeatherLat && liveWeatherLon) {
        const lat = liveWeatherLat.getAttribute('data-live-weather-lat');
        const lon = liveWeatherLon.getAttribute('data-live-weather-lon');

        promises.push(weatherApiFetch(lat, lon));
    }

    if (skiAreaToubizId) {
        const id = skiAreaToubizId.getAttribute('data-live-ski-area-toubiz-id');
        promises.push(skiAreaFetch(id));
    }

    // Fetch content
    await Promise.all(promises);

    // Show all content containers and hide all loaders
    liveSectionContent.forEach(item => item.classList.remove('hidden'));
    liveSectionLoader.forEach(item => item.classList.add('hidden'));

    // Update DOM
    setWeatherData();
    setSkiAreaData();
});
