import { RECIPES } from '../data/catalog.js?v=8';
import { MEAL_SLOTS } from '../planner/mealSlots.js';
import { applyFilters, getFilterState } from './RecipeList.js';

const FILTER_PANEL_TRANSITION = 'opacity 180ms ease, transform 180ms ease';
const FILTER_SURFACE = '#2d2e2b';
const FILTER_SURFACE_SOFT = '#2f2f2d';
const FILTER_BORDER = '#444442';
const FILTER_BORDER_ACTIVE = '#787876';
const FILTER_CHIP_ACTIVE = '#23221e';
const FILTER_TEXT_PRIMARY = '#ddd6ca';
const FILTER_TEXT_SECONDARY = '#d7d2c8';
const FILTER_TEXT_MUTED = '#9b978f';
const FILTER_TEXT_DIM = '#7d7a74';
const FILTER_TEXT_ACTIVE = '#f2efe8';
const FILTER_TRACK = '#393937';
const FILTER_TRACK_FILL = '#56534f';
const PREP_TIME_MIN = 5;
const PREP_TIME_MAX = 120;
const PREP_TIME_STEP = 5;
const PREP_TIME_MIN_GAP = PREP_TIME_STEP;
const FILTER_RECIPE_BLUR = 'blur(3px) saturate(0.94)';
const FILTER_CONTEXTS = {
    recipes: {
        anchorShellId: 'recipe-search-shell',
        buttonId: 'recipe-filter-btn',
        getState: () => getFilterState(),
        applyState: (nextState) => applyFilters(nextState),
        showSlots: true,
    },
    plannerPicker: {
        anchorShellId: 'planner-picker-search-shell',
        buttonId: 'planner-picker-filter-btn',
        getState: () => window.getPlannerPickerFilterState?.() || ({
            slots: [],
            tags: [],
            minMinutes: PREP_TIME_MIN,
            maxMinutes: PREP_TIME_MAX,
        }),
        applyState: (nextState) => window.applyPlannerPickerFilters?.(nextState),
        showSlots: false,
    },
};

function escapeHtml(s) {
    return String(s)
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}

function collectAllTags() {
    const tags = new Set();
    for (const r of Object.values(RECIPES)) {
        for (const t of (r.tags || [])) tags.add(t);
    }
    return [...tags].sort((a, b) => a.localeCompare(b, 'pl'));
}

export function getFilterHTML() {
    return `
    <style id="filter-view-styles">
        #filter-view.filter-open {
            pointer-events: auto;
        }

        #filter-view .prep-time-range-track,
        #filter-view .prep-time-range-fill {
            border-radius: 9999px;
            height: 0.375rem;
        }

        #filter-view .prep-time-range-handle {
            width: 1rem;
            height: 1rem;
            border-radius: 9999px;
            border: 1px solid rgba(242,239,232,0.16);
            background: ${FILTER_TRACK_FILL};
            box-shadow: 0 0 0 1px rgba(0,0,0,0.12);
            touch-action: none;
            outline: none;
        }
    </style>
    <div id="filter-view" class="absolute inset-0 z-[70] hidden opacity-0 transition-opacity duration-150" style="pointer-events:none; background:rgba(0,0,0,0.5) !important; background-image:none !important;" aria-hidden="true">
        <div id="filter-panel" class="absolute flex flex-col overflow-hidden rounded-[1.5rem] border" style="background:${FILTER_SURFACE} !important; background-image:none !important; border-color:${FILTER_BORDER} !important; opacity:0; transform:translateY(-0.5rem) scale(0.98); transform-origin:top center; transition:${FILTER_PANEL_TRANSITION}; box-shadow:0 18px 40px rgba(0,0,0,0.34), 0 4px 12px rgba(0,0,0,0.18); width:min(calc(100% - 1.5rem), 22rem);">
            <div class="pointer-events-none absolute inset-x-0 top-0 h-px" style="background:rgba(242,239,232,0.12);" aria-hidden="true"></div>
            <div class="shrink-0 px-3.5 pt-3 pb-2 flex justify-end" style="background:${FILTER_SURFACE} !important; background-image:none !important;">
                <div class="min-w-0 flex items-center justify-end gap-2">
                    <button id="filter-clear-btn" type="button" class="shrink-0 h-8 px-3 rounded-full border text-[11px] font-semibold transition-colors" style="background:${FILTER_SURFACE_SOFT} !important; border-color:${FILTER_BORDER} !important; color:${FILTER_TEXT_SECONDARY} !important;">Wyczyść</button>
                </div>
            </div>

            <div id="filter-panel-body" class="min-h-0 flex-1 overflow-y-auto no-scrollbar px-4 pb-4 space-y-2.5" style="background:${FILTER_SURFACE} !important; background-image:none !important;">
                <section id="filter-slot-section" class="p-3.5" style="background:${FILTER_SURFACE} !important; background-image:none !important;">
                    <p class="text-[10px] font-bold uppercase tracking-wider mb-3" style="color:${FILTER_TEXT_MUTED};">Pora posiłku</p>
                    <div id="filter-slot-chips" class="flex flex-wrap gap-2"></div>
                </section>

                <section class="p-3.5" style="background:${FILTER_SURFACE} !important; background-image:none !important;">
                    <p class="text-[10px] font-bold uppercase tracking-wider mb-3" style="color:${FILTER_TEXT_MUTED};">Dieta i tagi</p>
                    <div id="filter-tag-chips" class="flex flex-wrap gap-2"></div>
                </section>

                <section class="p-3.5" style="background:${FILTER_SURFACE} !important; background-image:none !important;">
                    <div class="flex items-center justify-between gap-3 mb-3">
                        <div class="min-w-0">
                            <p class="text-[10px] font-bold uppercase tracking-wider" style="color:${FILTER_TEXT_MUTED};">Czas przygotowania</p>
                        </div>
                        <span id="time-display-range" class="shrink-0 text-[11px] font-semibold tabular-nums text-right" style="color:${FILTER_TEXT_ACTIVE};">5 min - 120 min</span>
                    </div>
                    <div class="px-1">
                        <div class="relative h-9">
                            <div class="prep-time-range-track absolute inset-x-0 top-1/2 -translate-y-1/2" style="background:${FILTER_TRACK};" aria-hidden="true"></div>
                            <div id="prep-time-range-fill" class="prep-time-range-fill absolute top-1/2 -translate-y-1/2" style="background:${FILTER_TRACK_FILL}; left:0%; width:100%;" aria-hidden="true"></div>
                            <button
                                type="button"
                                id="prep-time-min-handle"
                                class="prep-time-range-handle absolute top-1/2 z-[2] -translate-x-1/2 -translate-y-1/2"
                                style="left:0%;"
                                data-time-handle="min"
                                role="slider"
                                aria-label="Minimalny czas przygotowania"
                                aria-valuemin="${PREP_TIME_MIN}"
                                aria-valuemax="${PREP_TIME_MAX}"
                                aria-valuenow="${PREP_TIME_MIN}"
                                aria-valuetext="${PREP_TIME_MIN} min"
                            ></button>
                            <button
                                type="button"
                                id="prep-time-max-handle"
                                class="prep-time-range-handle absolute top-1/2 z-[3] -translate-x-1/2 -translate-y-1/2"
                                style="left:100%;"
                                data-time-handle="max"
                                role="slider"
                                aria-label="Maksymalny czas przygotowania"
                                aria-valuemin="${PREP_TIME_MIN}"
                                aria-valuemax="${PREP_TIME_MAX}"
                                aria-valuenow="${PREP_TIME_MAX}"
                                aria-valuetext="120 min"
                            ></button>
                        </div>
                    </div>
                </section>
            </div>
        </div>
    </div>
    `;
}

let localSlots = [];
let localTags = [];
let localMinMinutes = PREP_TIME_MIN;
let localMaxMinutes = PREP_TIME_MAX;
let closeTimer = null;
let activeFilterContext = 'recipes';

function getActiveFilterConfig() {
    return FILTER_CONTEXTS[activeFilterContext] || FILTER_CONTEXTS.recipes;
}

function normalizeTimeRange(minMinutes, maxMinutes) {
    let nextMin = snapTimeValue(minMinutes);
    let nextMax = snapTimeValue(maxMinutes);

    nextMin = Math.min(Math.max(nextMin, PREP_TIME_MIN), PREP_TIME_MAX - PREP_TIME_MIN_GAP);
    nextMax = Math.max(Math.min(nextMax, PREP_TIME_MAX), PREP_TIME_MIN + PREP_TIME_MIN_GAP);

    if (nextMax - nextMin < PREP_TIME_MIN_GAP) {
        if (nextMin + PREP_TIME_MIN_GAP <= PREP_TIME_MAX) nextMax = nextMin + PREP_TIME_MIN_GAP;
        else nextMin = nextMax - PREP_TIME_MIN_GAP;
    }

    return { minMinutes: nextMin, maxMinutes: nextMax };
}

function formatTimeValue(minutes) {
    return `${minutes} min`;
}

function formatTimeRangeSummary(minMinutes, maxMinutes) {
    return `${formatTimeValue(minMinutes)} - ${formatTimeValue(maxMinutes)}`;
}

function getChipStyle(active) {
    const background = active ? FILTER_CHIP_ACTIVE : FILTER_SURFACE_SOFT;
    const border = active ? FILTER_BORDER_ACTIVE : FILTER_BORDER;
    const color = active ? FILTER_TEXT_ACTIVE : FILTER_TEXT_SECONDARY;
    return `background:${background} !important; background-image:none !important; box-shadow:none !important; border-color:${border} !important; color:${color} !important;`;
}

function clampTimeValue(value) {
    return Math.min(Math.max(value, PREP_TIME_MIN), PREP_TIME_MAX);
}

function snapTimeValue(value) {
    const steps = Math.round((clampTimeValue(value) - PREP_TIME_MIN) / PREP_TIME_STEP);
    return PREP_TIME_MIN + steps * PREP_TIME_STEP;
}

function getSliderPercent(value) {
    return ((value - PREP_TIME_MIN) / (PREP_TIME_MAX - PREP_TIME_MIN)) * 100;
}

function setActiveTimeHandle(activeHandle) {
    const minHandle = document.getElementById('prep-time-min-handle');
    const maxHandle = document.getElementById('prep-time-max-handle');
    if (!minHandle || !maxHandle) return;

    minHandle.style.zIndex = activeHandle === 'min' ? '4' : '2';
    maxHandle.style.zIndex = activeHandle === 'max' ? '4' : '3';
}

function syncTimeRangeUI() {
    const minHandle = document.getElementById('prep-time-min-handle');
    const maxHandle = document.getElementById('prep-time-max-handle');
    const rangeDisplay = document.getElementById('time-display-range');
    const rangeFill = document.getElementById('prep-time-range-fill');
    const start = getSliderPercent(localMinMinutes);
    const end = getSliderPercent(localMaxMinutes);

    if (minHandle) {
        minHandle.style.left = `${start}%`;
        minHandle.setAttribute('aria-valuenow', String(localMinMinutes));
        minHandle.setAttribute('aria-valuetext', formatTimeValue(localMinMinutes));
    }

    if (maxHandle) {
        maxHandle.style.left = `${end}%`;
        maxHandle.setAttribute('aria-valuenow', String(localMaxMinutes));
        maxHandle.setAttribute('aria-valuetext', formatTimeValue(localMaxMinutes));
    }

    if (rangeDisplay) rangeDisplay.textContent = formatTimeRangeSummary(localMinMinutes, localMaxMinutes);
    if (rangeFill) {
        rangeFill.style.left = `${start}%`;
        rangeFill.style.width = `${Math.max(end - start, 0)}%`;
    }
}

function positionFilterPanel() {
    const view = document.getElementById('filter-view');
    const panel = document.getElementById('filter-panel');
    const body = document.getElementById('filter-panel-body');
    const { anchorShellId, buttonId } = getActiveFilterConfig();
    const searchShell = document.getElementById(anchorShellId);
    const button = document.getElementById(buttonId);
    if (!view || !panel || (!searchShell && !button)) return;

    const viewRect = view.getBoundingClientRect();
    const anchorRect = (searchShell || button).getBoundingClientRect();
    const gap = 8;
    const margin = 12;
    const width = Math.min(anchorRect.width, viewRect.width - margin * 2);
    const top = Math.max(margin, anchorRect.bottom - viewRect.top + gap);
    const left = Math.max(
        margin,
        Math.min(anchorRect.left - viewRect.left, viewRect.width - width - margin),
    );
    const maxHeight = Math.max(220, viewRect.height - top - margin);

    panel.style.width = `${width}px`;
    panel.style.left = `${left}px`;
    panel.style.top = `${top}px`;
    panel.style.maxHeight = `${maxHeight}px`;
    if (body) body.style.maxHeight = `${maxHeight - 56}px`;
}

function setRecipeAreaBlur(visible) {
    // Dark overlay on filter-view handles the dimming now
}

function showFilterPanel() {
    const view = document.getElementById('filter-view');
    const panel = document.getElementById('filter-panel');
    if (!view || !panel) return;

    clearTimeout(closeTimer);
    view.classList.remove('hidden');
    view.classList.add('filter-open');
    view.style.pointerEvents = 'auto';
    view.setAttribute('aria-hidden', 'false');
    positionFilterPanel();
    setRecipeAreaBlur(true);

    requestAnimationFrame(() => {
        view.classList.add('opacity-100');
        panel.style.opacity = '1';
        panel.style.transform = 'translateY(0) scale(1)';
    });
}

function hideFilterPanel() {
    const view = document.getElementById('filter-view');
    const panel = document.getElementById('filter-panel');
    if (!view || !panel) return;

    view.classList.remove('opacity-100', 'filter-open');
    view.style.pointerEvents = 'none';
    view.setAttribute('aria-hidden', 'true');
    panel.style.opacity = '0';
    panel.style.transform = 'translateY(-0.5rem) scale(0.98)';
    setRecipeAreaBlur(false);

    closeTimer = setTimeout(() => {
        view.classList.add('hidden');
    }, 180);
}

function isFilterPanelOpen() {
    return document.getElementById('filter-view')?.classList.contains('filter-open');
}

function renderSlotChips() {
    const wrap = document.getElementById('filter-slot-chips');
    if (!wrap) return;

    wrap.innerHTML = MEAL_SLOTS.map((slot) => {
        const active = localSlots.includes(slot.id);
        return `<button type="button" data-filter-slot="${escapeHtml(slot.id)}" class="px-3 py-1.5 rounded-full border text-[12px] font-semibold transition-colors" style="${getChipStyle(active)}">${escapeHtml(slot.label)}</button>`;
    }).join('');

    wrap.querySelectorAll('[data-filter-slot]').forEach((btn) => {
        btn.addEventListener('click', () => {
            const id = btn.dataset.filterSlot;
            const idx = localSlots.indexOf(id);
            if (idx >= 0) localSlots.splice(idx, 1);
            else localSlots.push(id);
            renderSlotChips();
            syncLiveFilters();
        });
    });
}

function renderTagChips() {
    const wrap = document.getElementById('filter-tag-chips');
    if (!wrap) return;

    const allTags = collectAllTags();
    wrap.innerHTML = allTags.map((tag) => {
        const active = localTags.includes(tag.toLowerCase());
        return `<button type="button" data-filter-tag="${escapeHtml(tag)}" class="px-3 py-1.5 rounded-full border text-[12px] font-semibold transition-colors" style="${getChipStyle(active)}">${escapeHtml(tag)}</button>`;
    }).join('');

    wrap.querySelectorAll('[data-filter-tag]').forEach((btn) => {
        btn.addEventListener('click', () => {
            const tag = btn.dataset.filterTag.toLowerCase();
            const idx = localTags.indexOf(tag);
            if (idx >= 0) localTags.splice(idx, 1);
            else localTags.push(tag);
            renderTagChips();
            syncLiveFilters();
        });
    });
}

function syncFilterSections() {
    const slotSection = document.getElementById('filter-slot-section');
    if (!slotSection) return;
    slotSection.classList.toggle('hidden', !getActiveFilterConfig().showSlots);
}

function syncLiveFilters() {
    const config = getActiveFilterConfig();
    config.applyState?.({
        slots: config.showSlots ? localSlots : [],
        tags: localTags,
        minMinutes: localMinMinutes,
        maxMinutes: localMaxMinutes,
    });
}

export function setupFilter() {
    const rangeTrack = document.getElementById('prep-time-range-fill')?.parentElement;
    const minHandle = document.getElementById('prep-time-min-handle');
    const maxHandle = document.getElementById('prep-time-max-handle');
    const filterView = document.getElementById('filter-view');
    let activeTimeHandle = null;

    setRecipeAreaBlur(false);

    function valueFromPointer(clientX) {
        if (!rangeTrack) return PREP_TIME_MIN;
        const rect = rangeTrack.getBoundingClientRect();
        if (rect.width <= 0) return PREP_TIME_MIN;
        const ratio = Math.min(Math.max((clientX - rect.left) / rect.width, 0), 1);
        return snapTimeValue(PREP_TIME_MIN + ratio * (PREP_TIME_MAX - PREP_TIME_MIN));
    }

    function applyDraggedTimeValue(handleName, nextValue) {
        const value = snapTimeValue(nextValue);
        if (handleName === 'min') {
            localMinMinutes = Math.min(value, localMaxMinutes - PREP_TIME_MIN_GAP);
            localMinMinutes = Math.max(localMinMinutes, PREP_TIME_MIN);
        } else {
            localMaxMinutes = Math.max(value, localMinMinutes + PREP_TIME_MIN_GAP);
            localMaxMinutes = Math.min(localMaxMinutes, PREP_TIME_MAX);
        }
        syncTimeRangeUI();
        syncLiveFilters();
    }

    function stopTimeHandleDrag() {
        activeTimeHandle = null;
        window.removeEventListener('pointermove', onWindowPointerMove);
        window.removeEventListener('pointerup', stopTimeHandleDrag);
        window.removeEventListener('pointercancel', stopTimeHandleDrag);
    }

    function onWindowPointerMove(e) {
        if (!activeTimeHandle) return;
        e.preventDefault();
        applyDraggedTimeValue(activeTimeHandle, valueFromPointer(e.clientX));
    }

    function startTimeHandleDrag(handleName, e) {
        activeTimeHandle = handleName;
        setActiveTimeHandle(handleName);
        applyDraggedTimeValue(handleName, valueFromPointer(e.clientX));
        window.addEventListener('pointermove', onWindowPointerMove);
        window.addEventListener('pointerup', stopTimeHandleDrag);
        window.addEventListener('pointercancel', stopTimeHandleDrag);
    }

    function handleTimeHandleKeydown(handleName, e) {
        let nextValue = handleName === 'min' ? localMinMinutes : localMaxMinutes;

        if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') nextValue -= PREP_TIME_STEP;
        else if (e.key === 'ArrowRight' || e.key === 'ArrowUp') nextValue += PREP_TIME_STEP;
        else if (e.key === 'Home') nextValue = PREP_TIME_MIN;
        else if (e.key === 'End') nextValue = PREP_TIME_MAX;
        else return;

        e.preventDefault();
        setActiveTimeHandle(handleName);
        applyDraggedTimeValue(handleName, nextValue);
    }

    syncTimeRangeUI();
    setActiveTimeHandle('max');

    if (minHandle) {
        minHandle.addEventListener('pointerdown', (e) => {
            e.preventDefault();
            startTimeHandleDrag('min', e);
        });
        minHandle.addEventListener('focus', () => {
            setActiveTimeHandle('min');
        });
        minHandle.addEventListener('keydown', (e) => {
            handleTimeHandleKeydown('min', e);
        });
    }

    if (maxHandle) {
        maxHandle.addEventListener('pointerdown', (e) => {
            e.preventDefault();
            startTimeHandleDrag('max', e);
        });
        maxHandle.addEventListener('focus', () => {
            setActiveTimeHandle('max');
        });
        maxHandle.addEventListener('keydown', (e) => {
            handleTimeHandleKeydown('max', e);
        });
    }

    rangeTrack?.addEventListener('pointerdown', (e) => {
        if (e.target.closest('[data-time-handle]')) return;
        const clickedValue = valueFromPointer(e.clientX);
        const distToMin = Math.abs(clickedValue - localMinMinutes);
        const distToMax = Math.abs(clickedValue - localMaxMinutes);
        const handleName = distToMin <= distToMax ? 'min' : 'max';
        e.preventDefault();
        startTimeHandleDrag(handleName, e);
    });

    filterView?.addEventListener('click', (e) => {
        if (e.composedPath().includes(document.getElementById('filter-panel'))) return;
        window.closeFilters();
    });

    window.addEventListener('resize', () => {
        if (isFilterPanelOpen()) positionFilterPanel();
    });

    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape' && isFilterPanelOpen()) window.closeFilters();
    });

    document.getElementById('filter-clear-btn')?.addEventListener('click', () => {
        localSlots = [];
        localTags = [];
        localMinMinutes = PREP_TIME_MIN;
        localMaxMinutes = PREP_TIME_MAX;
        syncTimeRangeUI();
        renderSlotChips();
        renderTagChips();
        syncLiveFilters();
    });

    window.openFilters = (contextName = 'recipes') => {
        if (isFilterPanelOpen() && activeFilterContext === contextName) {
            window.closeFilters();
            return;
        }

        activeFilterContext = FILTER_CONTEXTS[contextName] ? contextName : 'recipes';
        const config = getActiveFilterConfig();
        const state = config.getState?.() || {};
        localSlots = [...(state.slots || [])];
        localTags = [...(state.tags || [])];
        const normalized = normalizeTimeRange(
            Number.isFinite(state.minMinutes) ? state.minMinutes : PREP_TIME_MIN,
            Number.isFinite(state.maxMinutes) ? state.maxMinutes : PREP_TIME_MAX,
        );
        localMinMinutes = normalized.minMinutes;
        localMaxMinutes = normalized.maxMinutes;

        syncTimeRangeUI();

        renderSlotChips();
        renderTagChips();
        syncFilterSections();

        showFilterPanel();
    };

    window.closeFilters = () => {
        stopTimeHandleDrag();
        hideFilterPanel();
    };
}
