import './bootstrap';
import {
    ArrowUpLeft,
    BadgeCheck,
    Bed,
    Blocks,
    BookMarked,
    BookOpenCheck,
    BookOpenText,
    CalendarDays,
    ChevronLeft,
    ChevronRight,
    Clock3,
    CloudSun,
    Database,
    Dumbbell,
    FlaskConical,
    GraduationCap,
    Home,
    Landmark,
    Languages,
    LogIn,
    MapPin,
    MessagesSquare,
    Mic2,
    Microscope,
    Monitor,
    Moon,
    MoonStar,
    Scale,
    School,
    ScrollText,
    Send,
    Sparkle,
    Sparkles,
    Stethoscope,
    Sun,
    SunMedium,
    Sunrise,
    Sunset,
    UserPlus,
    UsersRound,
    createIcons,
} from 'lucide';

const lucideIcons = {
    ArrowUpLeft,
    BadgeCheck,
    Bed,
    Blocks,
    BookMarked,
    BookOpenCheck,
    BookOpenText,
    CalendarDays,
    ChevronLeft,
    ChevronRight,
    Clock3,
    CloudSun,
    Database,
    Dumbbell,
    FlaskConical,
    GraduationCap,
    Home,
    Landmark,
    Languages,
    LogIn,
    MapPin,
    MessagesSquare,
    Mic2,
    Microscope,
    Monitor,
    Moon,
    MoonStar,
    Scale,
    School,
    ScrollText,
    Send,
    Sparkle,
    Sparkles,
    Stethoscope,
    Sun,
    SunMedium,
    Sunrise,
    Sunset,
    UserPlus,
    UsersRound,
};

const kabul = {
    label: 'کابل، افغانستان',
    latitude: 34.5553,
    longitude: 69.2075,
    timeZone: 'Asia/Kabul',
};

const prayerNames = ['Fajr', 'Sunrise', 'Dhuhr', 'Asr', 'Maghrib', 'Isha'];
const prayerScheduleNames = ['Fajr', 'Dhuhr', 'Asr', 'Maghrib', 'Isha'];

function formatWithCalendar(date, locales, calendar, timeZone) {
    const candidates = Array.isArray(locales) ? locales : [locales];

    for (const locale of candidates) {
        const formatter = new Intl.DateTimeFormat(`${locale}-u-ca-${calendar}`, {
            weekday: 'long',
            year: 'numeric',
            month: 'long',
            day: 'numeric',
            timeZone,
        });

        if (formatter.resolvedOptions().calendar === calendar) {
            return formatter.format(date);
        }
    }

    return new Intl.DateTimeFormat(candidates[0], {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        timeZone,
    }).format(date);
}

function formatClock(date, timeZone) {
    return new Intl.DateTimeFormat('en-US', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: true,
        timeZone,
    }).format(date);
}

function formatApiDate(date, timeZone) {
    const parts = new Intl.DateTimeFormat('en-GB', {
        day: '2-digit',
        month: '2-digit',
        year: 'numeric',
        timeZone,
    }).formatToParts(date);

    const values = Object.fromEntries(parts.filter((part) => part.type !== 'literal').map((part) => [part.type, part.value]));

    return `${values.day}-${values.month}-${values.year}`;
}

function setText(id, value) {
    const element = document.getElementById(id);
    if (element) {
        element.textContent = value;
    }
}

function updateDateTime(place = kabul) {
    const now = new Date();
    const zone = place.timeZone || kabul.timeZone;

    setText('clock-time', formatClock(now, zone));
    setText('location-label', place.label || kabul.label);
    setText('date-gregorian', formatWithCalendar(now, 'ps-AF', 'gregory', zone));
    setText('date-hijri-qamari', formatWithCalendar(now, ['ar-SA', 'en-u-ca-islamic-umalqura'], 'islamic-umalqura', zone));
    setText('date-hijri-shamsi', formatWithCalendar(now, ['fa-AF', 'fa-IR'], 'persian', zone));
    updatePrayerCountdown();
}

function setPrayerStatus(message, busy = false) {
    const status = document.getElementById('prayer-status');
    if (!status) {
        return;
    }

    status.innerHTML = `<span></span><span>${message}</span>`;
    status.style.color = busy ? 'var(--green)' : 'var(--muted)';
}

function cleanPrayerTime(value) {
    return String(value || '--:--').replace(/\s*\(.+\)\s*/g, '');
}

function formatPrayerDisplayTime(value, widget) {
    const match = cleanPrayerTime(value).match(/^(\d{1,2}):(\d{2})/);
    if (!match) {
        return '--:--';
    }

    const hour = Number(match[1]);
    const minute = match[2];
    const suffix = hour >= 12 ? (widget?.dataset.pmLabel || 'PM') : (widget?.dataset.amLabel || 'AM');
    const displayHour = hour % 12 || 12;

    return `${String(displayHour).padStart(2, '0')}:${minute} ${suffix}`;
}

function timeToSeconds(value) {
    const match = cleanPrayerTime(value).match(/^(\d{1,2}):(\d{2})/);
    if (!match) {
        return null;
    }

    return (Number(match[1]) * 60 * 60) + (Number(match[2]) * 60);
}

function zonedClockSeconds(timeZone) {
    const parts = new Intl.DateTimeFormat('en-GB', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hourCycle: 'h23',
        timeZone,
    }).formatToParts(new Date());
    const values = Object.fromEntries(parts.filter((part) => part.type !== 'literal').map((part) => [part.type, part.value]));

    return (Number(values.hour) * 60 * 60) + (Number(values.minute) * 60) + Number(values.second);
}

function formatCountdown(totalSeconds) {
    const safeSeconds = Math.max(0, Math.floor(totalSeconds));
    const hours = Math.floor(safeSeconds / 3600);
    const minutes = Math.floor((safeSeconds % 3600) / 60);
    const seconds = safeSeconds % 60;

    return [hours, minutes, seconds].map((part) => String(part).padStart(2, '0')).join(':');
}

function updatePrayerCountdown() {
    const widget = document.getElementById('prayer-widget');
    const data = window.jrkPrayerTimings;
    if (!widget || !data?.timings) {
        return;
    }

    const now = zonedClockSeconds(data.timeZone || kabul.timeZone);
    let nextName = null;
    let remaining = Number.POSITIVE_INFINITY;

    prayerScheduleNames.forEach((name) => {
        const prayerSecond = timeToSeconds(data.timings[name]);
        if (prayerSecond === null) {
            return;
        }

        let delta = prayerSecond - now;
        if (delta <= 0) {
            delta += 24 * 60 * 60;
        }

        if (delta < remaining) {
            remaining = delta;
            nextName = name;
        }
    });

    if (!nextName) {
        return;
    }

    const activeCard = widget.querySelector(`[data-prayer-card="${nextName}"]`);
    const label = activeCard?.querySelector('span')?.textContent?.trim() || nextName;

    setText('next-prayer-name', label);
    setText('next-prayer-countdown', formatCountdown(remaining));

    widget.querySelectorAll('[data-prayer-card]').forEach((card) => {
        card.classList.toggle('is-next', card.dataset.prayerCard === nextName);
    });
}

async function fetchPrayerTimes(place) {
    const widget = document.getElementById('prayer-widget');
    if (!widget) {
        return;
    }

    const method = widget.dataset.method || '1';
    const school = widget.dataset.school || '1';
    const date = formatApiDate(new Date(), place.timeZone || kabul.timeZone);
    const url = new URL(`https://api.aladhan.com/v1/timings/${date}`);

    url.searchParams.set('latitude', place.latitude);
    url.searchParams.set('longitude', place.longitude);
    url.searchParams.set('method', method);
    url.searchParams.set('school', school);

    setPrayerStatus(widget.dataset.loading || 'Loading prayer times...', true);

    try {
        const response = await fetch(url.toString(), { headers: { Accept: 'application/json' } });
        if (!response.ok) {
            throw new Error('Prayer API unavailable');
        }

        const payload = await response.json();
        if (payload.code !== 200 || !payload.data?.timings) {
            throw new Error('Prayer API returned an invalid payload');
        }

        const timings = {};

        prayerNames.forEach((name) => {
            timings[name] = cleanPrayerTime(payload.data.timings[name]);
            const element = widget.querySelector(`[data-prayer="${name}"]`);
            if (element) {
                element.textContent = formatPrayerDisplayTime(timings[name], widget);
            }
        });

        window.jrkPrayerTimings = {
            timings,
            timeZone: place.timeZone || kabul.timeZone,
        };

        const source = document.getElementById('prayer-source');
        if (source) {
            source.textContent = (widget.dataset.sourceTemplate || 'Times for :place based on the Hanafi school.').replace(':place', place.label || kabul.label);
        }

        updatePrayerCountdown();
        setPrayerStatus(widget.dataset.loaded || 'Prayer times updated.', false);
    } catch {
        setPrayerStatus(widget.dataset.error || 'Prayer times could not be loaded.', false);
    }
}

function resolveLocation() {
    const browserZone = Intl.DateTimeFormat().resolvedOptions().timeZone || kabul.timeZone;

    if (!navigator.geolocation) {
        return Promise.resolve(kabul);
    }

    return new Promise((resolve) => {
        navigator.geolocation.getCurrentPosition(
            (position) => {
                resolve({
                    label: 'ستاسو اوسنی ځای',
                    latitude: position.coords.latitude,
                    longitude: position.coords.longitude,
                    timeZone: browserZone,
                });
            },
            () => resolve(kabul),
            {
                enableHighAccuracy: false,
                timeout: 7000,
                maximumAge: 1000 * 60 * 30,
            },
        );
    });
}

async function refreshLocation(useDeviceLocation = false) {
    updateDateTime(kabul);
    const place = useDeviceLocation ? await resolveLocation() : kabul;
    updateDateTime(place);
    await fetchPrayerTimes(place);
    window.jrkPlace = place;
}

function setupNav() {
    const toggle = document.querySelector('[data-nav-toggle]');
    const menu = document.querySelector('[data-nav-menu]');
    if (!toggle || !menu) {
        return;
    }

    toggle.addEventListener('click', () => {
        const isOpen = menu.classList.toggle('is-open');
        toggle.setAttribute('aria-expanded', String(isOpen));
    });
}

function setupLanguageSelects() {
    const measure = document.createElement('span');
    measure.style.cssText = 'position:absolute;visibility:hidden;white-space:pre;inset:auto;pointer-events:none;';
    document.body.appendChild(measure);

    const syncSelectWidth = (select) => {
        const label = select.options[select.selectedIndex]?.textContent?.trim() || '';
        const styles = window.getComputedStyle(select);
        measure.style.font = styles.font;
        measure.style.letterSpacing = styles.letterSpacing;
        measure.textContent = label;
        select.style.setProperty('--language-select-width', `${Math.ceil(measure.getBoundingClientRect().width) + 2}px`);
    };

    document.querySelectorAll('[data-language-select]').forEach((select) => {
        syncSelectWidth(select);

        select.addEventListener('change', () => {
            syncSelectWidth(select);

            if (select.value) {
                window.location.href = select.value;
            }
        });
    });
}

function setupFilters() {
    document.querySelectorAll('[data-filter-input]').forEach((input) => {
        const targetSelector = input.dataset.filterTarget;
        const targets = [...document.querySelectorAll(targetSelector)];

        input.addEventListener('input', () => {
            const needle = input.value.trim().toLowerCase();

            targets.forEach((target) => {
                const text = (target.dataset.filterText || target.textContent || '').toLowerCase();
                target.hidden = Boolean(needle) && !text.includes(needle);
            });
        });
    });
}

function setupTheme() {
    const root = document.documentElement;
    const saved = localStorage.getItem('jrk-theme');
    const preferredDark = window.matchMedia?.('(prefers-color-scheme: dark)').matches;
    const initial = saved || (preferredDark ? 'dark' : 'light');

    root.dataset.theme = initial;

    document.querySelectorAll('[data-theme-toggle]').forEach((button) => {
        button.addEventListener('click', () => {
            const next = root.dataset.theme === 'dark' ? 'light' : 'dark';
            root.dataset.theme = next;
            localStorage.setItem('jrk-theme', next);
        });
    });
}

function setupHeroSliders() {
    document.querySelectorAll('[data-hero-slider]').forEach((slider) => {
        const slides = [...slider.querySelectorAll('[data-hero-slide]')];
        const dots = [...slider.querySelectorAll('[data-hero-dot]')];
        const previous = slider.querySelector('[data-hero-prev]');
        const next = slider.querySelector('[data-hero-next]');
        const progress = slider.querySelector('[data-hero-progress]');
        const interval = Number(slider.dataset.interval || 6500);
        const reducedMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
        let index = 0;
        let timer;

        if (!slides.length) {
            return;
        }

        const resetProgress = () => {
            if (!progress || reducedMotion || slides.length < 2) {
                return;
            }

            progress.style.animation = 'none';
            progress.offsetHeight;
            progress.style.animation = `hero-progress ${interval}ms linear forwards`;
        };

        const render = (nextIndex) => {
            index = (nextIndex + slides.length) % slides.length;

            slides.forEach((slide, slideIndex) => {
                const isActive = slideIndex === index;
                slide.classList.toggle('is-active', isActive);
                slide.setAttribute('aria-hidden', String(!isActive));
            });

            dots.forEach((dot, dotIndex) => {
                const isActive = dotIndex === index;
                dot.classList.toggle('is-active', isActive);
                dot.setAttribute('aria-current', isActive ? 'true' : 'false');
            });

            resetProgress();
        };

        const stop = () => {
            window.clearInterval(timer);
        };

        const start = () => {
            stop();

            if (!reducedMotion && slides.length > 1) {
                timer = window.setInterval(() => render(index + 1), interval);
            }
        };

        previous?.addEventListener('click', () => {
            render(index - 1);
            start();
        });

        next?.addEventListener('click', () => {
            render(index + 1);
            start();
        });

        dots.forEach((dot, dotIndex) => {
            dot.addEventListener('click', () => {
                render(dotIndex);
                start();
            });
        });

        slider.addEventListener('mouseenter', stop);
        slider.addEventListener('mouseleave', start);
        slider.addEventListener('focusin', stop);
        slider.addEventListener('focusout', start);

        render(0);
        start();
    });
}

document.addEventListener('DOMContentLoaded', () => {
    createIcons({ icons: lucideIcons });
    setupTheme();
    setupNav();
    setupLanguageSelects();
    setupFilters();
    setupHeroSliders();
    refreshLocation(true);

    setInterval(() => updateDateTime(window.jrkPlace || kabul), 1000);
});
