import { withCacheBuster } from './utils.js';
import { extractMetadataFromBlob } from './metadata.js';

const FILTER_STORAGE_KEY = 'gemini-app-history-filter';
const SEARCH_STORAGE_KEY = 'gemini-app-history-search';
const FAVORITES_STORAGE_KEY = 'gemini-app-history-favorites';
const SOURCE_STORAGE_KEY = 'gemini-app-history-source';
const VALID_SOURCES = ['generated', 'uploads'];
const DEFAULT_STATE = {
    filter: 'all',
    search: '',
    favorites: false,
};

function createStateMap(fallback) {
    return {
        generated: fallback,
        uploads: fallback,
    };
}

function parseStoredMap(key, fallback) {
    const defaultMap = createStateMap(fallback);
    let raw;
    try {
        raw = localStorage.getItem(key);
        if (!raw) return defaultMap;
        const parsed = JSON.parse(raw);
        if (parsed && typeof parsed === 'object') {
            return {
                generated: parsed.generated ?? parsed.default ?? fallback,
                uploads: parsed.uploads ?? parsed.default ?? fallback,
            };
        }
        // Backward compatibility: single value string or number
        return createStateMap(raw);
    } catch (e) {
        // If parsing failed but raw exists, treat it as a primitive single value
        if (raw) {
            return createStateMap(raw);
        }
        console.warn('Failed to load history state', e);
        return defaultMap;
    }
}

function persistStateMap(key, map) {
    try {
        localStorage.setItem(key, JSON.stringify(map));
    } catch (e) {
        console.warn('Failed to save history state', e);
    }
}

export function createGallery({ galleryGrid, onSelect }) {
    let currentFilter = DEFAULT_STATE.filter;
    let searchQuery = DEFAULT_STATE.search;
    let currentSource = 'generated';
    let allImages = [];
    let favorites = [];
    let showOnlyFavorites = DEFAULT_STATE.favorites;
    const stateBySource = {
        generated: { ...DEFAULT_STATE },
        uploads: { ...DEFAULT_STATE },
    };

    // Load saved filter, search and favorites from localStorage (per source)
    const savedFilters = parseStoredMap(FILTER_STORAGE_KEY, DEFAULT_STATE.filter);
    const savedSearches = parseStoredMap(SEARCH_STORAGE_KEY, DEFAULT_STATE.search);
    const savedFavorites = parseStoredMap(FAVORITES_STORAGE_KEY, DEFAULT_STATE.favorites);

    stateBySource.generated.filter = savedFilters.generated;
    stateBySource.uploads.filter = savedFilters.uploads;
    stateBySource.generated.search = savedSearches.generated;
    stateBySource.uploads.search = savedSearches.uploads;
    stateBySource.generated.favorites = savedFavorites.generated;
    stateBySource.uploads.favorites = savedFavorites.uploads;

    try {
        const savedSource = localStorage.getItem(SOURCE_STORAGE_KEY);
        if (savedSource && VALID_SOURCES.includes(savedSource)) {
            currentSource = savedSource;
        }
    } catch (e) {
        console.warn('Failed to load history source', e);
    }

    function applySourceState(source) {
        const state = stateBySource[source] || DEFAULT_STATE;
        currentFilter = state.filter ?? DEFAULT_STATE.filter;
        searchQuery = state.search ?? DEFAULT_STATE.search;
        showOnlyFavorites = state.favorites ?? DEFAULT_STATE.favorites;
    }

    applySourceState(currentSource);

    // Load favorites from backend
    async function loadFavorites() {
        try {
            const response = await fetch('/gallery_favorites');
            const data = await response.json();
            favorites = data.favorites || [];
        } catch (error) {
            console.warn('Failed to load gallery favorites', error);
        }
    }

    function extractRelativePath(imageUrl) {
        if (!imageUrl) return '';
        try {
            const url = new URL(imageUrl, window.location.origin);
            const path = url.pathname;
            const staticIndex = path.indexOf('/static/');
            if (staticIndex !== -1) {
                return path.slice(staticIndex + '/static/'.length).replace(/^\//, '');
            }
            return path.replace(/^\//, '');
        } catch (error) {
            const parts = imageUrl.split('/static/');
            if (parts[1]) return parts[1].split('?')[0];
            return imageUrl.split('/').pop().split('?')[0];
        }
    }

    function getFavoriteKey(imageUrl) {
        const relative = extractRelativePath(imageUrl);
        if (relative) return relative;
        const filename = imageUrl.split('/').pop().split('?')[0];
        return `${currentSource}/${filename}`;
    }

    function isFavorite(imageUrl) {
        const key = getFavoriteKey(imageUrl);
        const filename = imageUrl.split('/').pop().split('?')[0];
        return favorites.includes(key) || favorites.includes(filename);
    }

    // Date comparison utilities
    function getFileTimestamp(imageUrl) {
        // Extract date from filename format: model_yyyymmdd_id.png
        // Example: gemini-3-pro-image-preview_20251125_1.png
        const filename = imageUrl.split('/').pop().split('?')[0];
        const match = filename.match(/_(\d{8})_/); // Match yyyymmdd between underscores
        if (match) {
            const dateStr = match[1]; // e.g., "20251125"
            const year = parseInt(dateStr.substring(0, 4), 10);
            const month = parseInt(dateStr.substring(4, 6), 10) - 1; // Month is 0-indexed
            const day = parseInt(dateStr.substring(6, 8), 10);
            return new Date(year, month, day).getTime();
        }
        return null;
    }

    function isToday(timestamp) {
        if (!timestamp) return false;
        const date = new Date(timestamp);
        const today = new Date();
        return date.toDateString() === today.toDateString();
    }

    function isThisWeek(timestamp) {
        if (!timestamp) return false;
        const date = new Date(timestamp);
        const today = new Date();
        const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
        return date >= weekAgo && date <= today;
    }

    function isThisMonth(timestamp) {
        if (!timestamp) return false;
        const date = new Date(timestamp);
        const today = new Date();
        return date.getMonth() === today.getMonth() && 
               date.getFullYear() === today.getFullYear();
    }

    function isThisYear(timestamp) {
        if (!timestamp) return false;
        const date = new Date(timestamp);
        const today = new Date();
        return date.getFullYear() === today.getFullYear();
    }

    function matchesSearch(imageUrl) {
        if (!searchQuery) return true;
        const filename = imageUrl.split('/').pop().split('?')[0];
        return filename.toLowerCase().includes(searchQuery.toLowerCase());
    }

    function shouldShowImage(imageUrl) {
        // First check text search
        if (!matchesSearch(imageUrl)) return false;
        
        // Check favorites toggle - if enabled, only show favorites
        if (showOnlyFavorites && !isFavorite(imageUrl)) {
            return false;
        }
        
        // Then check date filter
        if (currentFilter === 'all') return true;
        
        const timestamp = getFileTimestamp(imageUrl);
        if (!timestamp) return currentFilter === 'all';
        
        switch (currentFilter) {
            case 'today':
                return isToday(timestamp);
            case 'week':
                return isThisWeek(timestamp);
            case 'month':
                return isThisMonth(timestamp);
            case 'year':
                return isThisYear(timestamp);
            default:
                return true;
        }
    }

    async function toggleFavorite(imageUrl) {
        const filename = imageUrl.split('/').pop().split('?')[0];
        const relativePath = extractRelativePath(imageUrl);
        
        try {
            const response = await fetch('/toggle_gallery_favorite', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    filename,
                    path: relativePath,
                    source: currentSource
                })
            });
            
            const data = await response.json();
            if (data.favorites) {
                favorites = data.favorites;
                renderGallery();
            }
        } catch (error) {
            console.error('Failed to toggle favorite', error);
        }
    }

    async function readMetadataFromImage(imageUrl) {
        try {
            const response = await fetch(withCacheBuster(imageUrl));
            if (!response.ok) return null;
            const blob = await response.blob();
            return await extractMetadataFromBlob(blob);
        } catch (error) {
            console.warn('Unable to read gallery metadata', error);
            return null;
        }
    }

    function renderGallery() {
        if (!galleryGrid) return;
        galleryGrid.innerHTML = '';

        const filteredImages = allImages.filter(shouldShowImage);

        filteredImages.forEach(imageUrl => {
            const div = document.createElement('div');
            div.className = 'gallery-item';
            
            // Image container for positioning
            div.style.position = 'relative';

            const img = document.createElement('img');
            img.src = withCacheBuster(imageUrl);
            img.loading = 'lazy';
            img.draggable = true;
            img.dataset.source = imageUrl;
            
            // Click to select
            div.addEventListener('click', async (e) => {
                // Don't select if clicking delete or favorite button
                if (e.target.closest('.delete-btn') || e.target.closest('.favorite-btn')) return;
                
                const metadata = await readMetadataFromImage(imageUrl);
                await onSelect?.({ imageUrl, metadata });
                const siblings = galleryGrid.querySelectorAll('.gallery-item');
                siblings.forEach(el => el.classList.remove('active'));
                div.classList.add('active');
            });

            img.addEventListener('dragstart', event => {
                event.dataTransfer?.setData('text/uri-list', imageUrl);
                event.dataTransfer?.setData('text/plain', imageUrl);
                if (event.dataTransfer) {
                    event.dataTransfer.effectAllowed = 'copy';
                }
            });
            
            // Toolbar for buttons
            const toolbar = document.createElement('div');
            toolbar.className = 'gallery-item-toolbar';
            
            // Favorite button
            const favoriteBtn = document.createElement('button');
            favoriteBtn.className = 'favorite-btn';
            if (isFavorite(imageUrl)) {
                favoriteBtn.classList.add('active');
            }
            favoriteBtn.innerHTML = `<svg width="16" height="16" viewBox="0 0 24 24" fill="${isFavorite(imageUrl) ? 'currentColor' : 'none'}" stroke="currentColor" stroke-width="2">
                <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
            </svg>`;
            favoriteBtn.title = isFavorite(imageUrl) ? 'Remove from favorites' : 'Add to favorites';
            favoriteBtn.addEventListener('click', async (e) => {
                e.stopPropagation();
                await toggleFavorite(imageUrl);
            });
            
            // Delete button
            const deleteBtn = document.createElement('button');
            deleteBtn.className = 'delete-btn';
            deleteBtn.innerHTML = '×';
            deleteBtn.title = 'Delete image';
            deleteBtn.addEventListener('click', async (e) => {
                e.stopPropagation();

                
                const filename = imageUrl.split('/').pop().split('?')[0];
                const relativePath = extractRelativePath(imageUrl);
                try {
                    const res = await fetch('/delete_image', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            filename,
                            path: relativePath,
                            source: currentSource
                        })
                    });
                    
                    if (res.ok) {
                        div.remove();
                        // Also remove from allImages array
                        allImages = allImages.filter(url => url !== imageUrl);
                    } else {
                        console.error('Failed to delete image');
                    }
                } catch (err) {
                    console.error('Error deleting image:', err);
                }
            });

            toolbar.appendChild(favoriteBtn);
            toolbar.appendChild(deleteBtn);

            div.appendChild(img);
            div.appendChild(toolbar);
            galleryGrid.appendChild(div);
        });
    }

    async function load() {
        if (!galleryGrid) return;
        try {
            await loadFavorites();
            const response = await fetch(`/gallery?source=${currentSource}&t=${new Date().getTime()}`);
            const data = await response.json();
            allImages = data.images || [];
            renderGallery();
        } catch (error) {
            console.error('Failed to load gallery:', error);
        }
    }

    function setFilter(filterType) {
        if (currentFilter === filterType) return;
        currentFilter = filterType;
        stateBySource[currentSource].filter = filterType;
        
        persistStateMap(FILTER_STORAGE_KEY, {
            generated: stateBySource.generated.filter,
            uploads: stateBySource.uploads.filter,
        });
        
        renderGallery();
    }

    function setSearch(query) {
        searchQuery = query || '';
        stateBySource[currentSource].search = searchQuery;
        
        persistStateMap(SEARCH_STORAGE_KEY, {
            generated: stateBySource.generated.search,
            uploads: stateBySource.uploads.search,
        });
        
        renderGallery();
    }

    function toggleFavorites() {
        showOnlyFavorites = !showOnlyFavorites;
        stateBySource[currentSource].favorites = showOnlyFavorites;
        persistStateMap(FAVORITES_STORAGE_KEY, {
            generated: stateBySource.generated.favorites,
            uploads: stateBySource.uploads.favorites,
        });
        renderGallery();
        return showOnlyFavorites;
    }

    function setSource(source, { resetFilters = false } = {}) {
        const normalized = VALID_SOURCES.includes(source) ? source : 'generated';
        currentSource = normalized;
        try {
            localStorage.setItem(SOURCE_STORAGE_KEY, currentSource);
        } catch (e) {
            console.warn('Failed to save history source', e);
        }
        if (resetFilters) {
            stateBySource[currentSource] = { ...DEFAULT_STATE };
            persistStateMap(FILTER_STORAGE_KEY, {
                generated: stateBySource.generated.filter,
                uploads: stateBySource.uploads.filter,
            });
            persistStateMap(SEARCH_STORAGE_KEY, {
                generated: stateBySource.generated.search,
                uploads: stateBySource.uploads.search,
            });
            persistStateMap(FAVORITES_STORAGE_KEY, {
                generated: stateBySource.generated.favorites,
                uploads: stateBySource.uploads.favorites,
            });
        }
        applySourceState(currentSource);
        return load();
    }

    function getCurrentFilter() {
        return currentFilter;
    }

    function getSearchQuery() {
        return searchQuery;
    }

    function getCurrentSource() {
        return currentSource;
    }

    function isFavoritesActive() {
        return showOnlyFavorites;
    }

    function setFavoritesActive(active) {
        showOnlyFavorites = Boolean(active);
        stateBySource[currentSource].favorites = showOnlyFavorites;
        persistStateMap(FAVORITES_STORAGE_KEY, {
            generated: stateBySource.generated.favorites,
            uploads: stateBySource.uploads.favorites,
        });
        renderGallery();
        return showOnlyFavorites;
    }

    function setSearchQuery(value) {
        setSearch(value);
    }

    function navigate(direction) {
        const activeItem = galleryGrid.querySelector('.gallery-item.active');
        
        if (!activeItem) {
            // If nothing active, select the first item on any arrow key
            const firstItem = galleryGrid.querySelector('.gallery-item');
            if (firstItem) {
                firstItem.click();
                firstItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
            }
            return;
        }

        let targetItem;
        if (direction === 'prev') {
            targetItem = activeItem.previousElementSibling;
        } else if (direction === 'next') {
            targetItem = activeItem.nextElementSibling;
        }

        if (targetItem && targetItem.classList.contains('gallery-item')) {
            targetItem.click();
            targetItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        }
    }

    // Setup keyboard navigation
    document.addEventListener('keydown', (e) => {
        // Ignore if user is typing in an input
        if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
        
        if (e.key === 'ArrowLeft') {
            navigate('prev');
        } else if (e.key === 'ArrowRight') {
            navigate('next');
        }
    });

    return { 
        load, 
        setFilter, 
        getCurrentFilter, 
        setSearch, 
        getSearchQuery, 
        toggleFavorites, 
        isFavoritesActive, 
        setSource, 
        getCurrentSource,
        setFavoritesActive,
        setSearchQuery
    };
}
